/*
 [The "BSD licence"]
 Copyright (c) 2015, John Snyders
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
 1. Redistributions of source code must retain the above copyright
 notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
 notice, this list of conditions and the following disclaimer in the
 documentation and/or other materials provided with the distribution.
 3. The name of the author may not be used to endorse or promote products
 derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

export default (function() {
  /*
   * Generated by PEG.js 0.8.0.
   *
   * http://pegjs.majda.cz/
   */

  function peg$subclass(child, parent) {
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor();
  }

  function SyntaxError(message, expected, found, offset, line, column) {
    this.message  = message;
    this.expected = expected;
    this.found    = found;
    this.offset   = offset;
    this.line     = line;
    this.column   = column;

    this.name     = "SyntaxError";
  }

  peg$subclass(SyntaxError, Error);

  function parse(input) {
    var options = arguments.length > 1 ? arguments[1] : {},

        peg$FAILED = {},

        peg$startRuleFunctions = { groupFile: peg$parsegroupFile, templateFile: peg$parsetemplateFile, templateFileRaw: peg$parsetemplateFileRaw, templateAndEOF: peg$parsetemplateAndEOF },
        peg$startRuleFunction  = peg$parsegroupFile,

        peg$c0 = peg$FAILED,
        peg$c1 = null,
        peg$c2 = [],
        peg$c3 = function() {
                    return curGroup;
                },
        peg$c4 = "import",
        peg$c5 = { type: "literal", value: "import", description: "\"import\"" },
        peg$c6 = function(file) {
                    curGroup.addImports(file.value);
                    return null;
                },
        peg$c7 = "delimiters",
        peg$c8 = { type: "literal", value: "delimiters", description: "\"delimiters\"" },
        peg$c9 = ",",
        peg$c10 = { type: "literal", value: ",", description: "\",\"" },
        peg$c11 = function(s, e) {
                    var start = s.value,
                        stop = e.value;
                    if (start.length !== 1 || stop.length !== 1) {
                        error("Delimiter value must be exactly one character");
                    }
                    if (VALID_DELIMITERS.indexOf(start) < 0 || VALID_DELIMITERS.indexOf(stop) < 0) {
                        error("Invalid delimiter character");
                    }
                    delimiterStartChar=s.value.charAt(0);
                    delimiterStopChar=e.value.charAt(0);
                    verboseLog("Delimiters: " + delimiterStartChar + ", " + delimiterStopChar);
                    return null;
                },
        peg$c12 = function() { return null; },
        peg$c13 = "@",
        peg$c14 = { type: "literal", value: "@", description: "\"@\"" },
        peg$c15 = ".",
        peg$c16 = { type: "literal", value: ".", description: "\".\"" },
        peg$c17 = "(",
        peg$c18 = { type: "literal", value: "(", description: "\"(\"" },
        peg$c19 = ")",
        peg$c20 = { type: "literal", value: ")", description: "\")\"" },
        peg$c21 = function(enclosing, n) {
                            // todo region stuff
                            return {
                                name: n.value,
                                enclosingTemplate: enclosing.value
                            };
                        },
        peg$c22 = function(n, args) {
                            return {
                                name: n.value,
                                args: args
                            };
                        },
        peg$c23 = "::=",
        peg$c24 = { type: "literal", value: "::=", description: "\"::=\"" },
        peg$c25 = function(s) { return s.value; },
        peg$c26 = function() { error("Missing template"); },
        peg$c27 = function(def, template) {
                    if (def.enclosingTemplate) {
                        verboseLog("Region definition: " + def.enclosingTemplate + "." + def.name);
                        def.template = parseTemplate(template).value;
                        curGroup.addRegion(def);
                    } else {
                        verboseLog("Template definition: " + def.name);
                        def.template = parseTemplate(template).value;
                        curGroup.addTemplate(def);
                    }
                    return null;
                },
        peg$c28 = function(alias, target) {
                    verboseLog("Template alias: " + alias.value + " > " + target.value);
                    curGroup.addTemplateAlias(alias.value, target.value);
                    return null;
                },
        peg$c29 = function() { formalArgsHasOptional = false; return true; },
        peg$c30 = void 0,
        peg$c31 = function(e) { return e; },
        peg$c32 = function(first, rest) {
                    return makeList(first, rest);
                },
        peg$c33 = function() { return []; },
        peg$c34 = "=",
        peg$c35 = { type: "literal", value: "=", description: "\"=\"" },
        peg$c36 = function(v) {
                                formalArgsHasOptional = true;
                                return v;
                            },
        peg$c37 = function(name, defaultValue) {
                        var ret;

                        if (formalArgsHasOptional && defaultValue === null) {
                            error("Required argument after optional not allowed.");
                        }
                        ret = {
                            type: "FORMAL_ARG",
                            loc: getLocation(),
                            name: name.value
                        };
                        if (defaultValue) {
                            ret.defaultValue = defaultValue;
                        }
                        return ret;
                    },
        peg$c38 = function(id) { curDict = { name: id.value, map: {}, default: null }; },
        peg$c39 = function() {
                    verboseLog("Dictionary definition: " + curDict.name);
                    curGroup.addDictionary(curDict);
                    curDict = null;
                    return null;
                },
        peg$c40 = "[",
        peg$c41 = { type: "literal", value: "[", description: "\"[\"" },
        peg$c42 = "]",
        peg$c43 = { type: "literal", value: "]", description: "\"]\"" },
        peg$c44 = "default",
        peg$c45 = { type: "literal", value: "default", description: "\"default\"" },
        peg$c46 = ":",
        peg$c47 = { type: "literal", value: ":", description: "\":\"" },
        peg$c48 = function(v) { curDict.default = v; },
        peg$c49 = function(k, v) { curDict.map[k.value] = v; },
        peg$c50 = function(v) {
                    return {
                        type: "ANON_TEMPLATE",
                        loc: getLocation(),
                        value: parseTemplate(v.value).value
                    };
                },
        peg$c51 = "key",
        peg$c52 = { type: "literal", value: "key", description: "\"key\"" },
        peg$c53 = function() { return { type: "DICT_KEY_VALUE", loc: getLocation(), value: null }; },
        peg$c54 = "{",
        peg$c55 = { type: "literal", value: "{", description: "\"{\"" },
        peg$c56 = function() {subtemplateDepth += 1; return true;},
        peg$c57 = "}",
        peg$c58 = { type: "literal", value: "}", description: "\"}\"" },
        peg$c59 = function(t) {
                    subtemplateDepth -= 1; // xxx is this subtemplate depth stuff needed?
                    return {
                        type: "ANON_TEMPLATE",
                        loc: getLocation(),
                        value: t.value
                    };
                },
        peg$c60 = function(name, args, template) {
                    if (name.value !== curGroup.fileName) {
                        error("Template name must match filename.");
                    }
                    verboseLog("Template definition: " + name.value);
                    curGroup.addTemplate({
                        name: name.value,
                        args: args,
                        template: parseTemplate(template).value
                    });
                    return curGroup;
                },
        peg$c61 = function(t) {
                    return t;
                },
        peg$c62 = function(t) {
                    curGroup.addTemplate({
                        name: curGroup.fileName,
                        args: null, // xxx is this OK?
                        template: t.value
                    });
                    return curGroup;
                },
        peg$c63 = "elseif",
        peg$c64 = { type: "literal", value: "elseif", description: "\"elseif\"" },
        peg$c65 = "else",
        peg$c66 = { type: "literal", value: "else", description: "\"else\"" },
        peg$c67 = "endif",
        peg$c68 = { type: "literal", value: "endif", description: "\"endif\"" },
        peg$c69 = function(i) { return i; },
        peg$c70 = function(e) { return {
                        type: "TEMPLATE",
                        value: e || null // xxx should this be null or text token with empty string value
                    };
                },
        peg$c71 = function() {return column() === 1;},
        peg$c72 = function(i, se) {
                    if (ignoreNewLines) {
                        return se;
                    } else {
                        return {
                            type: "INDENTED_EXPR",
                            loc: getLocation(),
                            indent: i.value,
                            value: se
                        };
                    }
                },
        peg$c73 = function() { outside = true; return true; },
        peg$c74 = function(se) {
                    return se;
                },
        peg$c75 = function(ce) {
                    return ce;
                },
        peg$c76 = function(n) {
                    if (ignoreNewLines) {
                        return null;
                    } else {
                        return n;
                    }
                },
        peg$c77 = ";",
        peg$c78 = { type: "literal", value: ";", description: "\";\"" },
        peg$c79 = function(o) { return o; },
        peg$c80 = function(e, opts) {
        	        var ret = {
        	            type: "EXPR",
                        loc: getLocation(),
        	            expr: e
        	        };
        	        if (opts) {
        	            ret.options = opts;
        	        }
        	        return ret;
                },
        peg$c81 = "@end",
        peg$c82 = { type: "literal", value: "@end", description: "\"@end\"" },
        peg$c83 = "|",
        peg$c84 = { type: "literal", value: "|", description: "\"|\"" },
        peg$c85 = function(a) {return a;},
        peg$c86 = function(args, t) {
                    subtemplateDepth -= 1;
                    outside = false;
                    return {
                        type: "SUBTEMPLATE",
                        loc: getLocation(),
                        args: args,
                        template: t.value
                    };
                },
        peg$c87 = function(a) { return {
                                                    type: "FORMAL_ARG",
                                                    loc: getLocation(),
                                                    name: a.value
                                                };
                                            },
        peg$c88 = function(first, rest) {
                    return makeList({type: "FORMAL_ARG", loc: getLocation(), name: first.value}, rest);
                },
        peg$c89 = "if",
        peg$c90 = { type: "literal", value: "if", description: "\"if\"" },
        peg$c91 = function(i) {inConditional = true; return true;},
        peg$c92 = function(i, c) {inConditional = false; return true;},
        peg$c93 = function() {inConditional = true; return true;},
        peg$c94 = function(c) {inConditional = false; return true;},
        peg$c95 = function(c, t) {
                        return {
                            type: "ELSEIF",
                            loc: getLocation(),
                            condition: c,
                            template: t.value
                        };
                    },
        peg$c96 = function(t) {
                        return {
                            type: "ELSE",
                            loc: getLocation(),
                            template: t.value
                        };
                    },
        peg$c97 = function(i, c, t, ei, e) {
                        return {
                            type: "IF",
                            loc: getLocation(),
                            condition: c,
                            template: t.value,
                            elseifPart: ei,
                            elsePart: e
                        };
                    },
        peg$c98 = "||",
        peg$c99 = { type: "literal", value: "||", description: "\"||\"" },
        peg$c100 = function(l, r) {
                    return {
                        type: "OR",
                        loc: getLocation(), 
                        left: l,
                        right: r
                    };
                },
        peg$c101 = "&&",
        peg$c102 = { type: "literal", value: "&&", description: "\"&&\"" },
        peg$c103 = function(l, r) {
                    return {
                        type: "AND",
                        loc: getLocation(), 
                        left: l,
                        right: r
                    };
                },
        peg$c104 = "!",
        peg$c105 = { type: "literal", value: "!", description: "\"!\"" },
        peg$c106 = function(n) {
                    return { 
                        type: "NOT",
                        loc: getLocation(), 
                        value: n
                    };
                },
        peg$c107 = function(name, val) {
                    var optionName = name.value,
                        value;
                    if (!curGroup.isValidOption(optionName)) {
                        error("No such option " + optionName);
                    }

                    value = val || curGroup.defaultOptionValue(optionName);
                    if (value === null) {
                        error("Value required for option " + optionName);
                    }
                    return {
                        name: optionName,
                        value: value
                    };
                },
        peg$c108 = function(tr) { return tr; },
        peg$c109 = function(me, ref) {
                    if (ref) {
                        return {
                            type: "MAP",
                            loc: getLocation(),
                            expr: me,
                            using: ref
                        };
                    } else {
                        return me;
                    }
                },
        peg$c110 = { type: "other", description: "expression" },
        peg$c111 = function(m) { return m; },
        peg$c112 = function(mn, tr) { return [ mn, tr ]; },
        peg$c113 = function(r) { return r; },
        peg$c114 = function(first, rest) { return makeList(first, rest); },
        peg$c115 = function(m1, zip, maps) {
                        var i, expr, res = m1;
                        if (zip) {
                            res = {
                                type: "ZIP",
                                loc: getLocation(),
                                expr: makeList(m1, zip[0]),
                                using: zip[1]
                            };
                        }
                        if (maps.length > 0) {
                            res = {
                                type: "MAP",
                                loc: getLocation(),
                                expr: res,
                                using: maps
                            };
                            // need to handle the implicit first argument
                            // xxx deal with array of arrays here
                            for (var i = 0; i < maps[0].length; i++) {
                                expr = maps[0][i];
                                if (expr.type === "INCLUDE") {
                                    expr.args.splice(0, 0, {
                                                           type: "STRING",
                                                           loc: getLocation(),
                                                           value: ""
                                                       });
                                }
                            }
                        }
                        return res;
                    },
        peg$c116 = function(i, a) {
                    return {
                        type: "INCLUDE",
                        loc: getLocation(),
                        templateName: i.value,
                        args: a.value,
                    };
                },
        peg$c117 = function(prop) {
                        return {
                            type: "PROP",
                            loc: getLocation(),
                            property: prop.value
                        };
                    },
        peg$c118 = function(e) {
                        return {
                            type: "PROP_IND",
                            loc: getLocation(),
                            property: e
                        };
                    },
        peg$c119 = function(e, props) {
                        if (props.length > 0) {
                            return {
                                type: "MEMBER_EXPR",
                                loc: getLocation(),
                                object: e,
                                properties: props  // xxx is this being an array a problem?
                            };
                        } else {
                            return e;
                        }
                    },
        peg$c120 = function(i) { return curGroup.isFunction(i.value); },
        peg$c121 = function(i, e) {
                    return {
                        type: "FUNCTION",
                        loc: getLocation(),
                        name: i.value,
                        arg: e
                    };
                },
        peg$c122 = "super.",
        peg$c123 = { type: "literal", value: "super.", description: "\"super.\"" },
        peg$c124 = function(i, a) { // xxx todo region stuff
                    return {
                        type: "INCLUDE_SUPER",
                        loc: getLocation(),
                        name: i.value,
                        args: a
                    };
                },
        peg$c125 = function(i, a) {
                     return {
                         type: "INCLUDE",
                         loc: getLocation(),
                         templateName: i.value,
                         args: a.value,
                         argsNamed: !!a.named,
                         argsPassThrough: !!a.passThrough
                     };
                 },
        peg$c126 = function(i) { return {
                        type: "ATTRIBUTE",
                        loc: getLocation(),
                        name: i.value
                    };
                },
        peg$c127 = function(s) { return s; },
        peg$c128 = function() {return inConditional;},
        peg$c129 = function(c) { return c; },
        peg$c130 = function() {return !inConditional;},
        peg$c131 = function(a) { return a; },
        peg$c132 = function(e, a) {
                    if (a) {
                        return {
                            type: "INCLUDE_IND",
                            loc: getLocation(),
                            expr: e,
                            args: a.value
                        };
                    } else {
                        return {
                            type: "TO_STR",
                            loc: getLocation(),
                            expr:  e
                        };
                    }
                },
        peg$c133 = "...",
        peg$c134 = { type: "literal", value: "...", description: "\"...\"" },
        peg$c135 = function(pt) { return true; },
        peg$c136 = function(first, rest, passThrough) {
        	        var ret = {
                        type: "ARGS",
                        value: makeList(first, rest),
                        named: true,
                        passThrough: !!passThrough
        	        };
        	        return ret;
        	    },
        peg$c137 = function() {
                    return {
                        type: "ARGS",
                        value: [],
                        passThrough: true
                    };
                },
        peg$c138 = function(first, rest) {
                    return {
                        type: "ARGS",
                        value: makeList(first, rest)
                    };
                },
        peg$c139 = function() {
                    return {
                        type: "ARGS",
                        value: []
                    };
                },
        peg$c140 = function(i, v) {
                    v.argName = i.value;
                    return v;
                },
        peg$c141 = function(first, rest) {
                    return {
                        type: "LIST",
                        loc: getLocation(),
                        value: makeList(first, rest)
                    };
                },
        peg$c142 = " ",
        peg$c143 = { type: "literal", value: " ", description: "\" \"" },
        peg$c144 = "\t",
        peg$c145 = { type: "literal", value: "\t", description: "\"\\t\"" },
        peg$c146 = { type: "other", description: "end of line" },
        peg$c147 = "\n",
        peg$c148 = { type: "literal", value: "\n", description: "\"\\n\"" },
        peg$c149 = "\r\n",
        peg$c150 = { type: "literal", value: "\r\n", description: "\"\\r\\n\"" },
        peg$c151 = "\r",
        peg$c152 = { type: "literal", value: "\r", description: "\"\\r\"" },
        peg$c153 = "/*",
        peg$c154 = { type: "literal", value: "/*", description: "\"/*\"" },
        peg$c155 = "*/",
        peg$c156 = { type: "literal", value: "*/", description: "\"*/\"" },
        peg$c157 = { type: "any", description: "any character" },
        peg$c158 = "//",
        peg$c159 = { type: "literal", value: "//", description: "\"//\"" },
        peg$c160 = { type: "other", description: "white space" },
        peg$c161 = { type: "other", description: "identifier" },
        peg$c162 = /^[a-zA-Z_\/]/,
        peg$c163 = { type: "class", value: "[a-zA-Z_\\/]", description: "[a-zA-Z_\\/]" },
        peg$c164 = /^[a-zA-Z_\/0-9]/,
        peg$c165 = { type: "class", value: "[a-zA-Z_\\/0-9]", description: "[a-zA-Z_\\/0-9]" },
        peg$c166 = function() {
        	        return {
        	            type: "ID",
        	            value: text()
        	        };
        	    },
        peg$c167 = "true",
        peg$c168 = { type: "literal", value: "true", description: "\"true\"" },
        peg$c169 = "false",
        peg$c170 = { type: "literal", value: "false", description: "\"false\"" },
        peg$c171 = "else ",
        peg$c172 = { type: "literal", value: "else ", description: "\"else \"" },
        peg$c173 = "elseif ",
        peg$c174 = { type: "literal", value: "elseif ", description: "\"elseif \"" },
        peg$c175 = "endif ",
        peg$c176 = { type: "literal", value: "endif ", description: "\"endif \"" },
        peg$c177 = "super",
        peg$c178 = { type: "literal", value: "super", description: "\"super\"" },
        peg$c179 = "group",
        peg$c180 = { type: "literal", value: "group", description: "\"group\"" },
        peg$c181 = function() { return { type: "BOOLEAN", loc: getLocation(), value: true }; },
        peg$c182 = function() { return { type: "BOOLEAN", loc: getLocation(), value: false }; },
        peg$c183 = function() { return { type: "EMPTY_LIST", loc: getLocation(), value: null }; },
        peg$c184 = { type: "other", description: "string" },
        peg$c185 = "\"",
        peg$c186 = { type: "literal", value: "\"", description: "\"\\\"\"" },
        peg$c187 = function(chars) {
                    return { type: "STRING", loc: getLocation(), value: chars.join("") };
                },
        peg$c188 = "\\",
        peg$c189 = { type: "literal", value: "\\", description: "\"\\\\\"" },
        peg$c190 = function() { return text(); },
        peg$c191 = function(sequence) { return sequence; },
        peg$c192 = function() { error("Unterminated string"); },
        peg$c193 = "n",
        peg$c194 = { type: "literal", value: "n", description: "\"n\"" },
        peg$c195 = function() { return "\n"; },
        peg$c196 = "r",
        peg$c197 = { type: "literal", value: "r", description: "\"r\"" },
        peg$c198 = function() { return "\r"; },
        peg$c199 = "t",
        peg$c200 = { type: "literal", value: "t", description: "\"t\"" },
        peg$c201 = function() { return "\t"; },
        peg$c202 = { type: "other", description: "big string" },
        peg$c203 = "<<",
        peg$c204 = { type: "literal", value: "<<", description: "\"<<\"" },
        peg$c205 = ">>",
        peg$c206 = { type: "literal", value: ">>", description: "\">>\"" },
        peg$c207 = function(chars) {
                    return {
                        type: "BIGSTRING",
                        value: chars.join("")
                    };
                },
        peg$c208 = "\\>>",
        peg$c209 = { type: "literal", value: "\\>>", description: "\"\\\\>>\"" },
        peg$c210 = ">\\>",
        peg$c211 = { type: "literal", value: ">\\>", description: "\">\\\\>\"" },
        peg$c212 = function() { return ">>"; },
        peg$c213 = function() { error("Unterminated big string"); },
        peg$c214 = "<%",
        peg$c215 = { type: "literal", value: "<%", description: "\"<%\"" },
        peg$c216 = "%>",
        peg$c217 = { type: "literal", value: "%>", description: "\"%>\"" },
        peg$c218 = function() {
                    var txt = text();
                    return {
                        type: "BIGSTRING_NO_NL",
                        value: { // xxx
                            ignoreNewLines: true,
                            // %\> is the escape to avoid end of string
                            string: txt.substring(2, txt.length - 2).replace(/\%\\>/g, "%>")
                        }
                    };
                },
        peg$c219 = { type: "other", description: "end of file" },
        peg$c220 = function() {return outside && column() === 1;},
        peg$c221 = function() {
                    return {
                        type: "INDENT",
                        value: text()
                    };
                },
        peg$c222 = function() {return outside;},
        peg$c223 = function() {
                    outside = false;
                    return { type: "START" };
                },
        peg$c224 = function() { return (input.charAt(peg$currPos) === delimiterStartChar); },
        peg$c225 = function() {
                    return { type: "ST_COMMENT" };
                },
        peg$c226 = function(chars) {
                    return {
                        type: "TEXT",
                        loc: getLocation(),
                        value: chars.join("") // can't use text() unless it fixes up escapes
                    };
                },
        peg$c227 = "\\\\",
        peg$c228 = { type: "literal", value: "\\\\", description: "\"\\\\\\\\\"" },
        peg$c229 = "\\}",
        peg$c230 = { type: "literal", value: "\\}", description: "\"\\\\}\"" },
        peg$c231 = function() {return subtemplateDepth > 0;},
        peg$c232 = function() {
                    return text();
                },
        peg$c233 = function() { return delimiterStartChar; },
        peg$c234 = function() { return "\\"; },
        peg$c235 = function() { return String.fromCharCode(125); },
        peg$c236 = function() { return ""; },
        peg$c237 = "u",
        peg$c238 = { type: "literal", value: "u", description: "\"u\"" },
        peg$c239 = function() { return String.fromCharCode(parseInt(text().substr(1), 16)); },
        peg$c240 = function() { return " "; },
        peg$c241 = function() {
                        error("Invalid escape character '" + text() + "'");
                    },
        peg$c242 = function(ch) { return ch; },
        peg$c243 = /^[0-9a-fA-F]/,
        peg$c244 = { type: "class", value: "[0-9a-fA-F]", description: "[0-9a-fA-F]" },
        peg$c245 = function() {
                    return {
                        type: "NEWLINE",
                        loc: getLocation(),
                        value: text()
                    };
                },
        peg$c246 = { type: "other", description: "stop delimiter" },
        peg$c247 = function() {
                    outside = true;
                    return { type: "STOP" };
                },
        peg$c248 = function() { return (input.charAt(peg$currPos) === delimiterStopChar); },

        peg$currPos          = 0,
        peg$reportedPos      = 0,
        peg$cachedPos        = 0,
        peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
        peg$maxFailPos       = 0,
        peg$maxFailExpected  = [],
        peg$silentFails      = 0,

        peg$result;

    if ("startRule" in options) {
      if (!(options.startRule in peg$startRuleFunctions)) {
        throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
      }

      peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
    }

    function text() {
      return input.substring(peg$reportedPos, peg$currPos);
    }

    function offset() {
      return peg$reportedPos;
    }

    function line() {
      return peg$computePosDetails(peg$reportedPos).line;
    }

    function column() {
      return peg$computePosDetails(peg$reportedPos).column;
    }

    function expected(description) {
      throw peg$buildException(
        null,
        [{ type: "other", description: description }],
        peg$reportedPos
      );
    }

    function error(message) {
      throw peg$buildException(message, null, peg$reportedPos);
    }

    function peg$computePosDetails(pos) {
      function advance(details, startPos, endPos) {
        var p, ch;

        for (p = startPos; p < endPos; p++) {
          ch = input.charAt(p);
          if (ch === "\n") {
            if (!details.seenCR) { details.line++; }
            details.column = 1;
            details.seenCR = false;
          } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
            details.line++;
            details.column = 1;
            details.seenCR = true;
          } else {
            details.column++;
            details.seenCR = false;
          }
        }
      }

      if (peg$cachedPos !== pos) {
        if (peg$cachedPos > pos) {
          peg$cachedPos = 0;
          peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
        }
        advance(peg$cachedPosDetails, peg$cachedPos, pos);
        peg$cachedPos = pos;
      }

      return peg$cachedPosDetails;
    }

    function peg$fail(expected) {
      if (peg$currPos < peg$maxFailPos) { return; }

      if (peg$currPos > peg$maxFailPos) {
        peg$maxFailPos = peg$currPos;
        peg$maxFailExpected = [];
      }

      peg$maxFailExpected.push(expected);
    }

    function peg$buildException(message, expected, pos) {
      function cleanupExpected(expected) {
        var i = 1;

        expected.sort(function(a, b) {
          if (a.description < b.description) {
            return -1;
          } else if (a.description > b.description) {
            return 1;
          } else {
            return 0;
          }
        });

        while (i < expected.length) {
          if (expected[i - 1] === expected[i]) {
            expected.splice(i, 1);
          } else {
            i++;
          }
        }
      }

      function buildMessage(expected, found) {
        function stringEscape(s) {
          function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }

          return s
            .replace(/\\/g,   '\\\\')
            .replace(/"/g,    '\\"')
            .replace(/\x08/g, '\\b')
            .replace(/\t/g,   '\\t')
            .replace(/\n/g,   '\\n')
            .replace(/\f/g,   '\\f')
            .replace(/\r/g,   '\\r')
            .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
            .replace(/[\x10-\x1F\x80-\xFF]/g,    function(ch) { return '\\x'  + hex(ch); })
            .replace(/[\u0180-\u0FFF]/g,         function(ch) { return '\\u0' + hex(ch); })
            .replace(/[\u1080-\uFFFF]/g,         function(ch) { return '\\u'  + hex(ch); });
        }

        var expectedDescs = new Array(expected.length),
            expectedDesc, foundDesc, i;

        for (i = 0; i < expected.length; i++) {
          expectedDescs[i] = expected[i].description;
        }

        expectedDesc = expected.length > 1
          ? expectedDescs.slice(0, -1).join(", ")
              + " or "
              + expectedDescs[expected.length - 1]
          : expectedDescs[0];

        foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";

        return "Expected " + expectedDesc + " but " + foundDesc + " found.";
      }

      var posDetails = peg$computePosDetails(pos),
          found      = pos < input.length ? input.charAt(pos) : null;

      if (expected !== null) {
        cleanupExpected(expected);
      }

      return new SyntaxError(
        message !== null ? message : buildMessage(expected, found),
        expected,
        found,
        pos,
        posDetails.line,
        posDetails.column
      );
    }

    function peg$parsegroupFile() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8;

      s0 = peg$currPos;
      s1 = peg$parse__();
      if (s1 !== peg$FAILED) {
        s2 = peg$parsedelimiters();
        if (s2 === peg$FAILED) {
          s2 = peg$c1;
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$parse__();
          if (s3 !== peg$FAILED) {
            s4 = [];
            s5 = peg$parseimport();
            while (s5 !== peg$FAILED) {
              s4.push(s5);
              s5 = peg$parseimport();
            }
            if (s4 !== peg$FAILED) {
              s5 = peg$parse__();
              if (s5 !== peg$FAILED) {
                s6 = [];
                s7 = peg$parsedef();
                while (s7 !== peg$FAILED) {
                  s6.push(s7);
                  s7 = peg$parsedef();
                }
                if (s6 !== peg$FAILED) {
                  s7 = peg$parse__();
                  if (s7 !== peg$FAILED) {
                    s8 = peg$parseEOF();
                    if (s8 !== peg$FAILED) {
                      peg$reportedPos = s0;
                      s1 = peg$c3();
                      s0 = s1;
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseimport() {
      var s0, s1, s2, s3, s4, s5;

      s0 = peg$currPos;
      s1 = peg$parse__();
      if (s1 !== peg$FAILED) {
        if (input.substr(peg$currPos, 6) === peg$c4) {
          s2 = peg$c4;
          peg$currPos += 6;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c5); }
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$parse__();
          if (s3 !== peg$FAILED) {
            s4 = peg$parseSTRING();
            if (s4 !== peg$FAILED) {
              s5 = peg$parse__();
              if (s5 !== peg$FAILED) {
                peg$reportedPos = s0;
                s1 = peg$c6(s4);
                s0 = s1;
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsedelimiters() {
      var s0, s1, s2, s3, s4, s5, s6, s7;

      s0 = peg$currPos;
      if (input.substr(peg$currPos, 10) === peg$c7) {
        s1 = peg$c7;
        peg$currPos += 10;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c8); }
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          s3 = peg$parseSTRING();
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 44) {
                s5 = peg$c9;
                peg$currPos++;
              } else {
                s5 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c10); }
              }
              if (s5 !== peg$FAILED) {
                s6 = peg$parse__();
                if (s6 !== peg$FAILED) {
                  s7 = peg$parseSTRING();
                  if (s7 !== peg$FAILED) {
                    peg$reportedPos = s0;
                    s1 = peg$c11(s3, s7);
                    s0 = s1;
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsedef() {
      var s0, s1, s2, s3;

      s0 = peg$currPos;
      s1 = peg$parse__();
      if (s1 !== peg$FAILED) {
        s2 = peg$parsedictDef();
        if (s2 !== peg$FAILED) {
          s3 = peg$parse__();
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c12();
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        s1 = peg$parse__();
        if (s1 !== peg$FAILED) {
          s2 = peg$parsetemplateDef();
          if (s2 !== peg$FAILED) {
            s3 = peg$parse__();
            if (s3 !== peg$FAILED) {
              peg$reportedPos = s0;
              s1 = peg$c12();
              s0 = s1;
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      }

      return s0;
    }

    function peg$parsetemplateDef() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8;

      s0 = peg$currPos;
      s1 = peg$currPos;
      if (input.charCodeAt(peg$currPos) === 64) {
        s2 = peg$c13;
        peg$currPos++;
      } else {
        s2 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c14); }
      }
      if (s2 !== peg$FAILED) {
        s3 = peg$parseID();
        if (s3 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 46) {
            s4 = peg$c15;
            peg$currPos++;
          } else {
            s4 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c16); }
          }
          if (s4 !== peg$FAILED) {
            s5 = peg$parseID();
            if (s5 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 40) {
                s6 = peg$c17;
                peg$currPos++;
              } else {
                s6 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c18); }
              }
              if (s6 !== peg$FAILED) {
                s7 = peg$parse__();
                if (s7 !== peg$FAILED) {
                  if (input.charCodeAt(peg$currPos) === 41) {
                    s8 = peg$c19;
                    peg$currPos++;
                  } else {
                    s8 = peg$FAILED;
                    if (peg$silentFails === 0) { peg$fail(peg$c20); }
                  }
                  if (s8 !== peg$FAILED) {
                    peg$reportedPos = s1;
                    s2 = peg$c21(s3, s5);
                    s1 = s2;
                  } else {
                    peg$currPos = s1;
                    s1 = peg$c0;
                  }
                } else {
                  peg$currPos = s1;
                  s1 = peg$c0;
                }
              } else {
                peg$currPos = s1;
                s1 = peg$c0;
              }
            } else {
              peg$currPos = s1;
              s1 = peg$c0;
            }
          } else {
            peg$currPos = s1;
            s1 = peg$c0;
          }
        } else {
          peg$currPos = s1;
          s1 = peg$c0;
        }
      } else {
        peg$currPos = s1;
        s1 = peg$c0;
      }
      if (s1 === peg$FAILED) {
        s1 = peg$currPos;
        s2 = peg$parseID();
        if (s2 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 40) {
            s3 = peg$c17;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c18); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              s5 = peg$parseformalArgs();
              if (s5 !== peg$FAILED) {
                s6 = peg$parse__();
                if (s6 !== peg$FAILED) {
                  if (input.charCodeAt(peg$currPos) === 41) {
                    s7 = peg$c19;
                    peg$currPos++;
                  } else {
                    s7 = peg$FAILED;
                    if (peg$silentFails === 0) { peg$fail(peg$c20); }
                  }
                  if (s7 !== peg$FAILED) {
                    peg$reportedPos = s1;
                    s2 = peg$c22(s2, s5);
                    s1 = s2;
                  } else {
                    peg$currPos = s1;
                    s1 = peg$c0;
                  }
                } else {
                  peg$currPos = s1;
                  s1 = peg$c0;
                }
              } else {
                peg$currPos = s1;
                s1 = peg$c0;
              }
            } else {
              peg$currPos = s1;
              s1 = peg$c0;
            }
          } else {
            peg$currPos = s1;
            s1 = peg$c0;
          }
        } else {
          peg$currPos = s1;
          s1 = peg$c0;
        }
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          if (input.substr(peg$currPos, 3) === peg$c23) {
            s3 = peg$c23;
            peg$currPos += 3;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c24); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              s5 = peg$currPos;
              s6 = peg$parseSTRING();
              if (s6 !== peg$FAILED) {
                peg$reportedPos = s5;
                s6 = peg$c25(s6);
              }
              s5 = s6;
              if (s5 === peg$FAILED) {
                s5 = peg$currPos;
                s6 = peg$parseBIGSTRING();
                if (s6 !== peg$FAILED) {
                  peg$reportedPos = s5;
                  s6 = peg$c25(s6);
                }
                s5 = s6;
                if (s5 === peg$FAILED) {
                  s5 = peg$currPos;
                  s6 = peg$parseBIGSTRING_NO_NL();
                  if (s6 !== peg$FAILED) {
                    peg$reportedPos = s5;
                    s6 = peg$c25(s6);
                  }
                  s5 = s6;
                  if (s5 === peg$FAILED) {
                    s5 = peg$currPos;
                    s6 = [];
                    if (s6 !== peg$FAILED) {
                      peg$reportedPos = s5;
                      s6 = peg$c26();
                    }
                    s5 = s6;
                  }
                }
              }
              if (s5 !== peg$FAILED) {
                peg$reportedPos = s0;
                s1 = peg$c27(s1, s5);
                s0 = s1;
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        s1 = peg$parseID();
        if (s1 !== peg$FAILED) {
          s2 = peg$parse__();
          if (s2 !== peg$FAILED) {
            if (input.substr(peg$currPos, 3) === peg$c23) {
              s3 = peg$c23;
              peg$currPos += 3;
            } else {
              s3 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c24); }
            }
            if (s3 !== peg$FAILED) {
              s4 = peg$parse__();
              if (s4 !== peg$FAILED) {
                s5 = peg$parseID();
                if (s5 !== peg$FAILED) {
                  peg$reportedPos = s0;
                  s1 = peg$c28(s1, s5);
                  s0 = s1;
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      }

      return s0;
    }

    function peg$parseformalArgs() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8;

      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c29();
      if (s1) {
        s1 = peg$c30;
      } else {
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parseformalArg();
        if (s2 !== peg$FAILED) {
          s3 = [];
          s4 = peg$currPos;
          s5 = peg$parse__();
          if (s5 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 44) {
              s6 = peg$c9;
              peg$currPos++;
            } else {
              s6 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c10); }
            }
            if (s6 !== peg$FAILED) {
              s7 = peg$parse__();
              if (s7 !== peg$FAILED) {
                s8 = peg$parseformalArg();
                if (s8 !== peg$FAILED) {
                  peg$reportedPos = s4;
                  s5 = peg$c31(s8);
                  s4 = s5;
                } else {
                  peg$currPos = s4;
                  s4 = peg$c0;
                }
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
          while (s4 !== peg$FAILED) {
            s3.push(s4);
            s4 = peg$currPos;
            s5 = peg$parse__();
            if (s5 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 44) {
                s6 = peg$c9;
                peg$currPos++;
              } else {
                s6 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c10); }
              }
              if (s6 !== peg$FAILED) {
                s7 = peg$parse__();
                if (s7 !== peg$FAILED) {
                  s8 = peg$parseformalArg();
                  if (s8 !== peg$FAILED) {
                    peg$reportedPos = s4;
                    s5 = peg$c31(s8);
                    s4 = s5;
                  } else {
                    peg$currPos = s4;
                    s4 = peg$c0;
                  }
                } else {
                  peg$currPos = s4;
                  s4 = peg$c0;
                }
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          }
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c32(s2, s3);
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        s1 = [];
        if (s1 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c33();
        }
        s0 = s1;
      }

      return s0;
    }

    function peg$parseformalArg() {
      var s0, s1, s2, s3, s4, s5, s6;

      s0 = peg$currPos;
      s1 = peg$parseID();
      if (s1 !== peg$FAILED) {
        s2 = peg$currPos;
        s3 = peg$parse__();
        if (s3 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 61) {
            s4 = peg$c34;
            peg$currPos++;
          } else {
            s4 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c35); }
          }
          if (s4 !== peg$FAILED) {
            s5 = peg$parse__();
            if (s5 !== peg$FAILED) {
              s6 = peg$parseSTRING();
              if (s6 === peg$FAILED) {
                s6 = peg$parseanonymousTemplate();
                if (s6 === peg$FAILED) {
                  s6 = peg$parseTRUE();
                  if (s6 === peg$FAILED) {
                    s6 = peg$parseFALSE();
                    if (s6 === peg$FAILED) {
                      s6 = peg$parseEMPTY_LIST();
                    }
                  }
                }
              }
              if (s6 !== peg$FAILED) {
                peg$reportedPos = s2;
                s3 = peg$c36(s6);
                s2 = s3;
              } else {
                peg$currPos = s2;
                s2 = peg$c0;
              }
            } else {
              peg$currPos = s2;
              s2 = peg$c0;
            }
          } else {
            peg$currPos = s2;
            s2 = peg$c0;
          }
        } else {
          peg$currPos = s2;
          s2 = peg$c0;
        }
        if (s2 === peg$FAILED) {
          s2 = peg$c1;
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c37(s1, s2);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsedictDef() {
      var s0, s1, s2, s3, s4, s5;

      s0 = peg$currPos;
      s1 = peg$currPos;
      s2 = peg$parse__();
      if (s2 !== peg$FAILED) {
        s3 = peg$parseID();
        if (s3 !== peg$FAILED) {
          s4 = peg$parse__();
          if (s4 !== peg$FAILED) {
            if (input.substr(peg$currPos, 3) === peg$c23) {
              s5 = peg$c23;
              peg$currPos += 3;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c24); }
            }
            if (s5 !== peg$FAILED) {
              peg$reportedPos = s1;
              s2 = peg$c38(s3);
              s1 = s2;
            } else {
              peg$currPos = s1;
              s1 = peg$c0;
            }
          } else {
            peg$currPos = s1;
            s1 = peg$c0;
          }
        } else {
          peg$currPos = s1;
          s1 = peg$c0;
        }
      } else {
        peg$currPos = s1;
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parsedict();
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c39();
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsedict() {
      var s0, s1, s2, s3, s4, s5, s6;

      s0 = peg$currPos;
      s1 = peg$parse__();
      if (s1 !== peg$FAILED) {
        if (input.charCodeAt(peg$currPos) === 91) {
          s2 = peg$c40;
          peg$currPos++;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c41); }
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$parse__();
          if (s3 !== peg$FAILED) {
            s4 = peg$parsedictPairs();
            if (s4 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 93) {
                s5 = peg$c42;
                peg$currPos++;
              } else {
                s5 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c43); }
              }
              if (s5 !== peg$FAILED) {
                s6 = peg$parse__();
                if (s6 !== peg$FAILED) {
                  s1 = [s1, s2, s3, s4, s5, s6];
                  s0 = s1;
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsedictPairs() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8;

      s0 = peg$currPos;
      s1 = peg$parse__();
      if (s1 !== peg$FAILED) {
        s2 = peg$parsekeyValuePair();
        if (s2 !== peg$FAILED) {
          s3 = [];
          s4 = peg$currPos;
          s5 = peg$parse__();
          if (s5 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 44) {
              s6 = peg$c9;
              peg$currPos++;
            } else {
              s6 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c10); }
            }
            if (s6 !== peg$FAILED) {
              s7 = peg$parse__();
              if (s7 !== peg$FAILED) {
                s8 = peg$parsekeyValuePair();
                if (s8 !== peg$FAILED) {
                  s5 = [s5, s6, s7, s8];
                  s4 = s5;
                } else {
                  peg$currPos = s4;
                  s4 = peg$c0;
                }
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
          while (s4 !== peg$FAILED) {
            s3.push(s4);
            s4 = peg$currPos;
            s5 = peg$parse__();
            if (s5 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 44) {
                s6 = peg$c9;
                peg$currPos++;
              } else {
                s6 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c10); }
              }
              if (s6 !== peg$FAILED) {
                s7 = peg$parse__();
                if (s7 !== peg$FAILED) {
                  s8 = peg$parsekeyValuePair();
                  if (s8 !== peg$FAILED) {
                    s5 = [s5, s6, s7, s8];
                    s4 = s5;
                  } else {
                    peg$currPos = s4;
                    s4 = peg$c0;
                  }
                } else {
                  peg$currPos = s4;
                  s4 = peg$c0;
                }
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$currPos;
            s5 = peg$parse__();
            if (s5 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 44) {
                s6 = peg$c9;
                peg$currPos++;
              } else {
                s6 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c10); }
              }
              if (s6 !== peg$FAILED) {
                s7 = peg$parse__();
                if (s7 !== peg$FAILED) {
                  s8 = peg$parsedefaultValuePair();
                  if (s8 !== peg$FAILED) {
                    s5 = [s5, s6, s7, s8];
                    s4 = s5;
                  } else {
                    peg$currPos = s4;
                    s4 = peg$c0;
                  }
                } else {
                  peg$currPos = s4;
                  s4 = peg$c0;
                }
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
            if (s4 === peg$FAILED) {
              s4 = peg$c1;
            }
            if (s4 !== peg$FAILED) {
              s1 = [s1, s2, s3, s4];
              s0 = s1;
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        s1 = peg$parse__();
        if (s1 !== peg$FAILED) {
          s2 = peg$parsedefaultValuePair();
          if (s2 !== peg$FAILED) {
            s1 = [s1, s2];
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      }

      return s0;
    }

    function peg$parsedefaultValuePair() {
      var s0, s1, s2, s3, s4, s5, s6;

      s0 = peg$currPos;
      if (input.substr(peg$currPos, 7) === peg$c44) {
        s1 = peg$c44;
        peg$currPos += 7;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c45); }
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 58) {
            s3 = peg$c46;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c47); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              s5 = peg$parsekeyValue();
              if (s5 !== peg$FAILED) {
                s6 = peg$parse__();
                if (s6 !== peg$FAILED) {
                  peg$reportedPos = s0;
                  s1 = peg$c48(s5);
                  s0 = s1;
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsekeyValuePair() {
      var s0, s1, s2, s3, s4, s5, s6;

      s0 = peg$currPos;
      s1 = peg$parseSTRING();
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 58) {
            s3 = peg$c46;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c47); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              s5 = peg$parsekeyValue();
              if (s5 !== peg$FAILED) {
                s6 = peg$parse__();
                if (s6 !== peg$FAILED) {
                  peg$reportedPos = s0;
                  s1 = peg$c49(s1, s5);
                  s0 = s1;
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsekeyValue() {
      var s0, s1;

      s0 = peg$currPos;
      s1 = peg$parseBIGSTRING();
      if (s1 !== peg$FAILED) {
        peg$reportedPos = s0;
        s1 = peg$c50(s1);
      }
      s0 = s1;
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        s1 = peg$parseBIGSTRING_NO_NL();
        if (s1 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c50(s1);
        }
        s0 = s1;
        if (s0 === peg$FAILED) {
          s0 = peg$parseSTRING();
          if (s0 === peg$FAILED) {
            s0 = peg$parseanonymousTemplate();
            if (s0 === peg$FAILED) {
              s0 = peg$parseTRUE();
              if (s0 === peg$FAILED) {
                s0 = peg$parseFALSE();
                if (s0 === peg$FAILED) {
                  s0 = peg$currPos;
                  if (input.substr(peg$currPos, 3) === peg$c51) {
                    s1 = peg$c51;
                    peg$currPos += 3;
                  } else {
                    s1 = peg$FAILED;
                    if (peg$silentFails === 0) { peg$fail(peg$c52); }
                  }
                  if (s1 !== peg$FAILED) {
                    peg$reportedPos = s0;
                    s1 = peg$c53();
                  }
                  s0 = s1;
                  if (s0 === peg$FAILED) {
                    s0 = peg$parseEMPTY_LIST();
                  }
                }
              }
            }
          }
        }
      }

      return s0;
    }

    function peg$parseanonymousTemplate() {
      var s0, s1, s2, s3, s4;

      s0 = peg$currPos;
      if (input.charCodeAt(peg$currPos) === 123) {
        s1 = peg$c54;
        peg$currPos++;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c55); }
      }
      if (s1 !== peg$FAILED) {
        peg$reportedPos = peg$currPos;
        s2 = peg$c56();
        if (s2) {
          s2 = peg$c30;
        } else {
          s2 = peg$c0;
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$parsetemplate();
          if (s3 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 125) {
              s4 = peg$c57;
              peg$currPos++;
            } else {
              s4 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c58); }
            }
            if (s4 !== peg$FAILED) {
              peg$reportedPos = s0;
              s1 = peg$c59(s3);
              s0 = s1;
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsetemplateFile() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12;

      s0 = peg$currPos;
      s1 = peg$parse__();
      if (s1 !== peg$FAILED) {
        s2 = peg$parseID();
        if (s2 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 40) {
            s3 = peg$c17;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c18); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              s5 = peg$parseformalArgs();
              if (s5 !== peg$FAILED) {
                s6 = peg$parse__();
                if (s6 !== peg$FAILED) {
                  if (input.charCodeAt(peg$currPos) === 41) {
                    s7 = peg$c19;
                    peg$currPos++;
                  } else {
                    s7 = peg$FAILED;
                    if (peg$silentFails === 0) { peg$fail(peg$c20); }
                  }
                  if (s7 !== peg$FAILED) {
                    s8 = peg$parse__();
                    if (s8 !== peg$FAILED) {
                      if (input.substr(peg$currPos, 3) === peg$c23) {
                        s9 = peg$c23;
                        peg$currPos += 3;
                      } else {
                        s9 = peg$FAILED;
                        if (peg$silentFails === 0) { peg$fail(peg$c24); }
                      }
                      if (s9 !== peg$FAILED) {
                        s10 = peg$parse__();
                        if (s10 !== peg$FAILED) {
                          s11 = peg$currPos;
                          s12 = peg$parseSTRING();
                          if (s12 !== peg$FAILED) {
                            peg$reportedPos = s11;
                            s12 = peg$c25(s12);
                          }
                          s11 = s12;
                          if (s11 === peg$FAILED) {
                            s11 = peg$currPos;
                            s12 = peg$parseBIGSTRING();
                            if (s12 !== peg$FAILED) {
                              peg$reportedPos = s11;
                              s12 = peg$c25(s12);
                            }
                            s11 = s12;
                            if (s11 === peg$FAILED) {
                              s11 = peg$currPos;
                              s12 = peg$parseBIGSTRING_NO_NL();
                              if (s12 !== peg$FAILED) {
                                peg$reportedPos = s11;
                                s12 = peg$c25(s12);
                              }
                              s11 = s12;
                              if (s11 === peg$FAILED) {
                                s11 = peg$currPos;
                                s12 = [];
                                if (s12 !== peg$FAILED) {
                                  peg$reportedPos = s11;
                                  s12 = peg$c26();
                                }
                                s11 = s12;
                              }
                            }
                          }
                          if (s11 !== peg$FAILED) {
                            s12 = peg$parse__();
                            if (s12 !== peg$FAILED) {
                              peg$reportedPos = s0;
                              s1 = peg$c60(s2, s5, s11);
                              s0 = s1;
                            } else {
                              peg$currPos = s0;
                              s0 = peg$c0;
                            }
                          } else {
                            peg$currPos = s0;
                            s0 = peg$c0;
                          }
                        } else {
                          peg$currPos = s0;
                          s0 = peg$c0;
                        }
                      } else {
                        peg$currPos = s0;
                        s0 = peg$c0;
                      }
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsetemplateAndEOF() {
      var s0, s1, s2;

      s0 = peg$currPos;
      s1 = peg$parsetemplate();
      if (s1 !== peg$FAILED) {
        s2 = peg$parseEOF();
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c61(s1);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsetemplateFileRaw() {
      var s0, s1, s2;

      s0 = peg$currPos;
      s1 = peg$parsetemplate();
      if (s1 !== peg$FAILED) {
        s2 = peg$parseEOF();
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c62(s1);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsetemplate() {
      var s0, s1, s2, s3, s4, s5, s6, s7;

      s0 = peg$currPos;
      s1 = [];
      s2 = peg$currPos;
      s3 = peg$currPos;
      peg$silentFails++;
      s4 = peg$currPos;
      s5 = peg$parseINDENT();
      if (s5 === peg$FAILED) {
        s5 = peg$c1;
      }
      if (s5 !== peg$FAILED) {
        s6 = peg$parseSTART_CHAR();
        if (s6 !== peg$FAILED) {
          if (input.substr(peg$currPos, 6) === peg$c63) {
            s7 = peg$c63;
            peg$currPos += 6;
          } else {
            s7 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c64); }
          }
          if (s7 !== peg$FAILED) {
            s5 = [s5, s6, s7];
            s4 = s5;
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
        } else {
          peg$currPos = s4;
          s4 = peg$c0;
        }
      } else {
        peg$currPos = s4;
        s4 = peg$c0;
      }
      if (s4 === peg$FAILED) {
        s4 = peg$currPos;
        s5 = peg$parseINDENT();
        if (s5 === peg$FAILED) {
          s5 = peg$c1;
        }
        if (s5 !== peg$FAILED) {
          s6 = peg$parseSTART_CHAR();
          if (s6 !== peg$FAILED) {
            if (input.substr(peg$currPos, 4) === peg$c65) {
              s7 = peg$c65;
              peg$currPos += 4;
            } else {
              s7 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c66); }
            }
            if (s7 !== peg$FAILED) {
              s5 = [s5, s6, s7];
              s4 = s5;
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
        } else {
          peg$currPos = s4;
          s4 = peg$c0;
        }
        if (s4 === peg$FAILED) {
          s4 = peg$currPos;
          s5 = peg$parseINDENT();
          if (s5 === peg$FAILED) {
            s5 = peg$c1;
          }
          if (s5 !== peg$FAILED) {
            s6 = peg$parseSTART_CHAR();
            if (s6 !== peg$FAILED) {
              if (input.substr(peg$currPos, 5) === peg$c67) {
                s7 = peg$c67;
                peg$currPos += 5;
              } else {
                s7 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c68); }
              }
              if (s7 !== peg$FAILED) {
                s5 = [s5, s6, s7];
                s4 = s5;
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
        }
      }
      peg$silentFails--;
      if (s4 === peg$FAILED) {
        s3 = peg$c30;
      } else {
        peg$currPos = s3;
        s3 = peg$c0;
      }
      if (s3 !== peg$FAILED) {
        s4 = peg$parseelement();
        if (s4 !== peg$FAILED) {
          peg$reportedPos = s2;
          s3 = peg$c69(s4);
          s2 = s3;
        } else {
          peg$currPos = s2;
          s2 = peg$c0;
        }
      } else {
        peg$currPos = s2;
        s2 = peg$c0;
      }
      while (s2 !== peg$FAILED) {
        s1.push(s2);
        s2 = peg$currPos;
        s3 = peg$currPos;
        peg$silentFails++;
        s4 = peg$currPos;
        s5 = peg$parseINDENT();
        if (s5 === peg$FAILED) {
          s5 = peg$c1;
        }
        if (s5 !== peg$FAILED) {
          s6 = peg$parseSTART_CHAR();
          if (s6 !== peg$FAILED) {
            if (input.substr(peg$currPos, 6) === peg$c63) {
              s7 = peg$c63;
              peg$currPos += 6;
            } else {
              s7 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c64); }
            }
            if (s7 !== peg$FAILED) {
              s5 = [s5, s6, s7];
              s4 = s5;
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
        } else {
          peg$currPos = s4;
          s4 = peg$c0;
        }
        if (s4 === peg$FAILED) {
          s4 = peg$currPos;
          s5 = peg$parseINDENT();
          if (s5 === peg$FAILED) {
            s5 = peg$c1;
          }
          if (s5 !== peg$FAILED) {
            s6 = peg$parseSTART_CHAR();
            if (s6 !== peg$FAILED) {
              if (input.substr(peg$currPos, 4) === peg$c65) {
                s7 = peg$c65;
                peg$currPos += 4;
              } else {
                s7 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c66); }
              }
              if (s7 !== peg$FAILED) {
                s5 = [s5, s6, s7];
                s4 = s5;
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
          if (s4 === peg$FAILED) {
            s4 = peg$currPos;
            s5 = peg$parseINDENT();
            if (s5 === peg$FAILED) {
              s5 = peg$c1;
            }
            if (s5 !== peg$FAILED) {
              s6 = peg$parseSTART_CHAR();
              if (s6 !== peg$FAILED) {
                if (input.substr(peg$currPos, 5) === peg$c67) {
                  s7 = peg$c67;
                  peg$currPos += 5;
                } else {
                  s7 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c68); }
                }
                if (s7 !== peg$FAILED) {
                  s5 = [s5, s6, s7];
                  s4 = s5;
                } else {
                  peg$currPos = s4;
                  s4 = peg$c0;
                }
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          }
        }
        peg$silentFails--;
        if (s4 === peg$FAILED) {
          s3 = peg$c30;
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        if (s3 !== peg$FAILED) {
          s4 = peg$parseelement();
          if (s4 !== peg$FAILED) {
            peg$reportedPos = s2;
            s3 = peg$c69(s4);
            s2 = s3;
          } else {
            peg$currPos = s2;
            s2 = peg$c0;
          }
        } else {
          peg$currPos = s2;
          s2 = peg$c0;
        }
      }
      if (s1 !== peg$FAILED) {
        peg$reportedPos = s0;
        s1 = peg$c70(s1);
      }
      s0 = s1;

      return s0;
    }

    function peg$parseelement() {
      var s0, s1, s2, s3, s4;

      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c71();
      if (s1) {
        s1 = peg$c30;
      } else {
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parseINDENT();
        if (s2 === peg$FAILED) {
          s2 = peg$c1;
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$parseST_COMMENT();
          if (s3 !== peg$FAILED) {
            s4 = peg$parseNEWLINE();
            if (s4 !== peg$FAILED) {
              peg$reportedPos = s0;
              s1 = peg$c12();
              s0 = s1;
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        s1 = peg$parseINDENT();
        if (s1 !== peg$FAILED) {
          s2 = peg$parsesingleElement();
          if (s2 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c72(s1, s2);
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          peg$reportedPos = peg$currPos;
          s1 = peg$c73();
          if (s1) {
            s1 = peg$c30;
          } else {
            s1 = peg$c0;
          }
          if (s1 !== peg$FAILED) {
            s2 = peg$parsesingleElement();
            if (s2 !== peg$FAILED) {
              peg$reportedPos = s0;
              s1 = peg$c74(s2);
              s0 = s1;
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
          if (s0 === peg$FAILED) {
            s0 = peg$currPos;
            peg$reportedPos = peg$currPos;
            s1 = peg$c73();
            if (s1) {
              s1 = peg$c30;
            } else {
              s1 = peg$c0;
            }
            if (s1 !== peg$FAILED) {
              s2 = peg$parsecompoundElement();
              if (s2 !== peg$FAILED) {
                peg$reportedPos = s0;
                s1 = peg$c75(s2);
                s0 = s1;
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          }
        }
      }

      return s0;
    }

    function peg$parsesingleElement() {
      var s0, s1;

      s0 = peg$parseTEXT();
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        s1 = peg$parseNEWLINE();
        if (s1 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c76(s1);
        }
        s0 = s1;
        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          s1 = peg$parseST_COMMENT();
          if (s1 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c12();
          }
          s0 = s1;
          if (s0 === peg$FAILED) {
            s0 = peg$parseexprTag();
          }
        }
      }

      return s0;
    }

    function peg$parsecompoundElement() {
      var s0;

      s0 = peg$parseifstat();
      if (s0 === peg$FAILED) {
        s0 = peg$parseregion();
      }

      return s0;
    }

    function peg$parseexprTag() {
      var s0, s1, s2, s3, s4, s5, s6;

      s0 = peg$currPos;
      s1 = peg$parseSTART();
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          s3 = peg$parseexpr();
          if (s3 !== peg$FAILED) {
            s4 = peg$currPos;
            if (input.charCodeAt(peg$currPos) === 59) {
              s5 = peg$c77;
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c78); }
            }
            if (s5 !== peg$FAILED) {
              s6 = peg$parseexprOptions();
              if (s6 !== peg$FAILED) {
                peg$reportedPos = s4;
                s5 = peg$c79(s6);
                s4 = s5;
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
            if (s4 === peg$FAILED) {
              s4 = peg$c1;
            }
            if (s4 !== peg$FAILED) {
              s5 = peg$parse__();
              if (s5 !== peg$FAILED) {
                s6 = peg$parseSTOP();
                if (s6 !== peg$FAILED) {
                  peg$reportedPos = s0;
                  s1 = peg$c80(s3, s4);
                  s0 = s1;
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseregion() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10;

      s0 = peg$currPos;
      s1 = peg$parseINDENT();
      if (s1 === peg$FAILED) {
        s1 = peg$c1;
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parseSTART();
        if (s2 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 64) {
            s3 = peg$c13;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c14); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parseID();
            if (s4 !== peg$FAILED) {
              s5 = peg$parseSTOP();
              if (s5 !== peg$FAILED) {
                s6 = peg$parsetemplate();
                if (s6 !== peg$FAILED) {
                  s7 = peg$parseINDENT();
                  if (s7 === peg$FAILED) {
                    s7 = peg$c1;
                  }
                  if (s7 !== peg$FAILED) {
                    s8 = peg$parseSTART();
                    if (s8 !== peg$FAILED) {
                      if (input.substr(peg$currPos, 4) === peg$c81) {
                        s9 = peg$c81;
                        peg$currPos += 4;
                      } else {
                        s9 = peg$FAILED;
                        if (peg$silentFails === 0) { peg$fail(peg$c82); }
                      }
                      if (s9 !== peg$FAILED) {
                        s10 = peg$parseSTOP();
                        if (s10 !== peg$FAILED) {
                          s1 = [s1, s2, s3, s4, s5, s6, s7, s8, s9, s10];
                          s0 = s1;
                        } else {
                          peg$currPos = s0;
                          s0 = peg$c0;
                        }
                      } else {
                        peg$currPos = s0;
                        s0 = peg$c0;
                      }
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsesubtemplate() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8;

      s0 = peg$currPos;
      if (input.charCodeAt(peg$currPos) === 123) {
        s1 = peg$c54;
        peg$currPos++;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c55); }
      }
      if (s1 !== peg$FAILED) {
        peg$reportedPos = peg$currPos;
        s2 = peg$c56();
        if (s2) {
          s2 = peg$c30;
        } else {
          s2 = peg$c0;
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$currPos;
          s4 = peg$parse__();
          if (s4 !== peg$FAILED) {
            s5 = peg$parseformalArgsNoDefault();
            if (s5 !== peg$FAILED) {
              s6 = peg$parse__();
              if (s6 !== peg$FAILED) {
                if (input.charCodeAt(peg$currPos) === 124) {
                  s7 = peg$c83;
                  peg$currPos++;
                } else {
                  s7 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c84); }
                }
                if (s7 !== peg$FAILED) {
                  s8 = peg$parse__();
                  if (s8 !== peg$FAILED) {
                    peg$reportedPos = s3;
                    s4 = peg$c85(s5);
                    s3 = s4;
                  } else {
                    peg$currPos = s3;
                    s3 = peg$c0;
                  }
                } else {
                  peg$currPos = s3;
                  s3 = peg$c0;
                }
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
          if (s3 === peg$FAILED) {
            s3 = peg$c1;
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parsetemplate();
            if (s4 !== peg$FAILED) {
              s5 = peg$parseINDENT();
              if (s5 === peg$FAILED) {
                s5 = peg$c1;
              }
              if (s5 !== peg$FAILED) {
                s6 = peg$parse__();
                if (s6 !== peg$FAILED) {
                  if (input.charCodeAt(peg$currPos) === 125) {
                    s7 = peg$c57;
                    peg$currPos++;
                  } else {
                    s7 = peg$FAILED;
                    if (peg$silentFails === 0) { peg$fail(peg$c58); }
                  }
                  if (s7 !== peg$FAILED) {
                    peg$reportedPos = s0;
                    s1 = peg$c86(s3, s4);
                    s0 = s1;
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseformalArgsNoDefault() {
      var s0, s1, s2, s3, s4, s5, s6, s7;

      s0 = peg$currPos;
      s1 = peg$parseID();
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$currPos;
        s4 = peg$parse__();
        if (s4 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 44) {
            s5 = peg$c9;
            peg$currPos++;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c10); }
          }
          if (s5 !== peg$FAILED) {
            s6 = peg$parse__();
            if (s6 !== peg$FAILED) {
              s7 = peg$parseID();
              if (s7 !== peg$FAILED) {
                peg$reportedPos = s3;
                s4 = peg$c87(s7);
                s3 = s4;
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$currPos;
          s4 = peg$parse__();
          if (s4 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 44) {
              s5 = peg$c9;
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c10); }
            }
            if (s5 !== peg$FAILED) {
              s6 = peg$parse__();
              if (s6 !== peg$FAILED) {
                s7 = peg$parseID();
                if (s7 !== peg$FAILED) {
                  peg$reportedPos = s3;
                  s4 = peg$c87(s7);
                  s3 = s4;
                } else {
                  peg$currPos = s3;
                  s3 = peg$c0;
                }
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c88(s1, s2);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseifstat() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29;

      s0 = peg$currPos;
      s1 = peg$parseINDENT();
      if (s1 === peg$FAILED) {
        s1 = peg$c1;
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parseSTART();
        if (s2 !== peg$FAILED) {
          if (input.substr(peg$currPos, 2) === peg$c89) {
            s3 = peg$c89;
            peg$currPos += 2;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c90); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 40) {
                s5 = peg$c17;
                peg$currPos++;
              } else {
                s5 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c18); }
              }
              if (s5 !== peg$FAILED) {
                s6 = peg$parse__();
                if (s6 !== peg$FAILED) {
                  peg$reportedPos = peg$currPos;
                  s7 = peg$c91(s1);
                  if (s7) {
                    s7 = peg$c30;
                  } else {
                    s7 = peg$c0;
                  }
                  if (s7 !== peg$FAILED) {
                    s8 = peg$parseconditional();
                    if (s8 !== peg$FAILED) {
                      peg$reportedPos = peg$currPos;
                      s9 = peg$c92(s1, s8);
                      if (s9) {
                        s9 = peg$c30;
                      } else {
                        s9 = peg$c0;
                      }
                      if (s9 !== peg$FAILED) {
                        s10 = peg$parse__();
                        if (s10 !== peg$FAILED) {
                          if (input.charCodeAt(peg$currPos) === 41) {
                            s11 = peg$c19;
                            peg$currPos++;
                          } else {
                            s11 = peg$FAILED;
                            if (peg$silentFails === 0) { peg$fail(peg$c20); }
                          }
                          if (s11 !== peg$FAILED) {
                            s12 = peg$parseSTOP();
                            if (s12 !== peg$FAILED) {
                              s13 = peg$parsetemplate();
                              if (s13 !== peg$FAILED) {
                                s14 = [];
                                s15 = peg$currPos;
                                s16 = peg$currPos;
                                peg$silentFails++;
                                s17 = peg$currPos;
                                s18 = peg$parseINDENT();
                                if (s18 === peg$FAILED) {
                                  s18 = peg$c1;
                                }
                                if (s18 !== peg$FAILED) {
                                  s19 = peg$parseSTART_CHAR();
                                  if (s19 !== peg$FAILED) {
                                    if (input.substr(peg$currPos, 4) === peg$c65) {
                                      s20 = peg$c65;
                                      peg$currPos += 4;
                                    } else {
                                      s20 = peg$FAILED;
                                      if (peg$silentFails === 0) { peg$fail(peg$c66); }
                                    }
                                    if (s20 !== peg$FAILED) {
                                      s21 = peg$parseSTOP_CHAR();
                                      if (s21 !== peg$FAILED) {
                                        s18 = [s18, s19, s20, s21];
                                        s17 = s18;
                                      } else {
                                        peg$currPos = s17;
                                        s17 = peg$c0;
                                      }
                                    } else {
                                      peg$currPos = s17;
                                      s17 = peg$c0;
                                    }
                                  } else {
                                    peg$currPos = s17;
                                    s17 = peg$c0;
                                  }
                                } else {
                                  peg$currPos = s17;
                                  s17 = peg$c0;
                                }
                                if (s17 === peg$FAILED) {
                                  s17 = peg$currPos;
                                  s18 = peg$parseINDENT();
                                  if (s18 === peg$FAILED) {
                                    s18 = peg$c1;
                                  }
                                  if (s18 !== peg$FAILED) {
                                    s19 = peg$parseSTART_CHAR();
                                    if (s19 !== peg$FAILED) {
                                      if (input.substr(peg$currPos, 5) === peg$c67) {
                                        s20 = peg$c67;
                                        peg$currPos += 5;
                                      } else {
                                        s20 = peg$FAILED;
                                        if (peg$silentFails === 0) { peg$fail(peg$c68); }
                                      }
                                      if (s20 !== peg$FAILED) {
                                        s21 = peg$parseSTOP_CHAR();
                                        if (s21 !== peg$FAILED) {
                                          s18 = [s18, s19, s20, s21];
                                          s17 = s18;
                                        } else {
                                          peg$currPos = s17;
                                          s17 = peg$c0;
                                        }
                                      } else {
                                        peg$currPos = s17;
                                        s17 = peg$c0;
                                      }
                                    } else {
                                      peg$currPos = s17;
                                      s17 = peg$c0;
                                    }
                                  } else {
                                    peg$currPos = s17;
                                    s17 = peg$c0;
                                  }
                                }
                                peg$silentFails--;
                                if (s17 === peg$FAILED) {
                                  s16 = peg$c30;
                                } else {
                                  peg$currPos = s16;
                                  s16 = peg$c0;
                                }
                                if (s16 !== peg$FAILED) {
                                  s17 = peg$parseINDENT();
                                  if (s17 === peg$FAILED) {
                                    s17 = peg$c1;
                                  }
                                  if (s17 !== peg$FAILED) {
                                    s18 = peg$parseSTART();
                                    if (s18 !== peg$FAILED) {
                                      if (input.substr(peg$currPos, 6) === peg$c63) {
                                        s19 = peg$c63;
                                        peg$currPos += 6;
                                      } else {
                                        s19 = peg$FAILED;
                                        if (peg$silentFails === 0) { peg$fail(peg$c64); }
                                      }
                                      if (s19 !== peg$FAILED) {
                                        s20 = peg$parse__();
                                        if (s20 !== peg$FAILED) {
                                          if (input.charCodeAt(peg$currPos) === 40) {
                                            s21 = peg$c17;
                                            peg$currPos++;
                                          } else {
                                            s21 = peg$FAILED;
                                            if (peg$silentFails === 0) { peg$fail(peg$c18); }
                                          }
                                          if (s21 !== peg$FAILED) {
                                            s22 = peg$parse__();
                                            if (s22 !== peg$FAILED) {
                                              peg$reportedPos = peg$currPos;
                                              s23 = peg$c93();
                                              if (s23) {
                                                s23 = peg$c30;
                                              } else {
                                                s23 = peg$c0;
                                              }
                                              if (s23 !== peg$FAILED) {
                                                s24 = peg$parseconditional();
                                                if (s24 !== peg$FAILED) {
                                                  peg$reportedPos = peg$currPos;
                                                  s25 = peg$c94(s24);
                                                  if (s25) {
                                                    s25 = peg$c30;
                                                  } else {
                                                    s25 = peg$c0;
                                                  }
                                                  if (s25 !== peg$FAILED) {
                                                    s26 = peg$parse__();
                                                    if (s26 !== peg$FAILED) {
                                                      if (input.charCodeAt(peg$currPos) === 41) {
                                                        s27 = peg$c19;
                                                        peg$currPos++;
                                                      } else {
                                                        s27 = peg$FAILED;
                                                        if (peg$silentFails === 0) { peg$fail(peg$c20); }
                                                      }
                                                      if (s27 !== peg$FAILED) {
                                                        s28 = peg$parseSTOP();
                                                        if (s28 !== peg$FAILED) {
                                                          s29 = peg$parsetemplate();
                                                          if (s29 !== peg$FAILED) {
                                                            peg$reportedPos = s15;
                                                            s16 = peg$c95(s24, s29);
                                                            s15 = s16;
                                                          } else {
                                                            peg$currPos = s15;
                                                            s15 = peg$c0;
                                                          }
                                                        } else {
                                                          peg$currPos = s15;
                                                          s15 = peg$c0;
                                                        }
                                                      } else {
                                                        peg$currPos = s15;
                                                        s15 = peg$c0;
                                                      }
                                                    } else {
                                                      peg$currPos = s15;
                                                      s15 = peg$c0;
                                                    }
                                                  } else {
                                                    peg$currPos = s15;
                                                    s15 = peg$c0;
                                                  }
                                                } else {
                                                  peg$currPos = s15;
                                                  s15 = peg$c0;
                                                }
                                              } else {
                                                peg$currPos = s15;
                                                s15 = peg$c0;
                                              }
                                            } else {
                                              peg$currPos = s15;
                                              s15 = peg$c0;
                                            }
                                          } else {
                                            peg$currPos = s15;
                                            s15 = peg$c0;
                                          }
                                        } else {
                                          peg$currPos = s15;
                                          s15 = peg$c0;
                                        }
                                      } else {
                                        peg$currPos = s15;
                                        s15 = peg$c0;
                                      }
                                    } else {
                                      peg$currPos = s15;
                                      s15 = peg$c0;
                                    }
                                  } else {
                                    peg$currPos = s15;
                                    s15 = peg$c0;
                                  }
                                } else {
                                  peg$currPos = s15;
                                  s15 = peg$c0;
                                }
                                while (s15 !== peg$FAILED) {
                                  s14.push(s15);
                                  s15 = peg$currPos;
                                  s16 = peg$currPos;
                                  peg$silentFails++;
                                  s17 = peg$currPos;
                                  s18 = peg$parseINDENT();
                                  if (s18 === peg$FAILED) {
                                    s18 = peg$c1;
                                  }
                                  if (s18 !== peg$FAILED) {
                                    s19 = peg$parseSTART_CHAR();
                                    if (s19 !== peg$FAILED) {
                                      if (input.substr(peg$currPos, 4) === peg$c65) {
                                        s20 = peg$c65;
                                        peg$currPos += 4;
                                      } else {
                                        s20 = peg$FAILED;
                                        if (peg$silentFails === 0) { peg$fail(peg$c66); }
                                      }
                                      if (s20 !== peg$FAILED) {
                                        s21 = peg$parseSTOP_CHAR();
                                        if (s21 !== peg$FAILED) {
                                          s18 = [s18, s19, s20, s21];
                                          s17 = s18;
                                        } else {
                                          peg$currPos = s17;
                                          s17 = peg$c0;
                                        }
                                      } else {
                                        peg$currPos = s17;
                                        s17 = peg$c0;
                                      }
                                    } else {
                                      peg$currPos = s17;
                                      s17 = peg$c0;
                                    }
                                  } else {
                                    peg$currPos = s17;
                                    s17 = peg$c0;
                                  }
                                  if (s17 === peg$FAILED) {
                                    s17 = peg$currPos;
                                    s18 = peg$parseINDENT();
                                    if (s18 === peg$FAILED) {
                                      s18 = peg$c1;
                                    }
                                    if (s18 !== peg$FAILED) {
                                      s19 = peg$parseSTART_CHAR();
                                      if (s19 !== peg$FAILED) {
                                        if (input.substr(peg$currPos, 5) === peg$c67) {
                                          s20 = peg$c67;
                                          peg$currPos += 5;
                                        } else {
                                          s20 = peg$FAILED;
                                          if (peg$silentFails === 0) { peg$fail(peg$c68); }
                                        }
                                        if (s20 !== peg$FAILED) {
                                          s21 = peg$parseSTOP_CHAR();
                                          if (s21 !== peg$FAILED) {
                                            s18 = [s18, s19, s20, s21];
                                            s17 = s18;
                                          } else {
                                            peg$currPos = s17;
                                            s17 = peg$c0;
                                          }
                                        } else {
                                          peg$currPos = s17;
                                          s17 = peg$c0;
                                        }
                                      } else {
                                        peg$currPos = s17;
                                        s17 = peg$c0;
                                      }
                                    } else {
                                      peg$currPos = s17;
                                      s17 = peg$c0;
                                    }
                                  }
                                  peg$silentFails--;
                                  if (s17 === peg$FAILED) {
                                    s16 = peg$c30;
                                  } else {
                                    peg$currPos = s16;
                                    s16 = peg$c0;
                                  }
                                  if (s16 !== peg$FAILED) {
                                    s17 = peg$parseINDENT();
                                    if (s17 === peg$FAILED) {
                                      s17 = peg$c1;
                                    }
                                    if (s17 !== peg$FAILED) {
                                      s18 = peg$parseSTART();
                                      if (s18 !== peg$FAILED) {
                                        if (input.substr(peg$currPos, 6) === peg$c63) {
                                          s19 = peg$c63;
                                          peg$currPos += 6;
                                        } else {
                                          s19 = peg$FAILED;
                                          if (peg$silentFails === 0) { peg$fail(peg$c64); }
                                        }
                                        if (s19 !== peg$FAILED) {
                                          s20 = peg$parse__();
                                          if (s20 !== peg$FAILED) {
                                            if (input.charCodeAt(peg$currPos) === 40) {
                                              s21 = peg$c17;
                                              peg$currPos++;
                                            } else {
                                              s21 = peg$FAILED;
                                              if (peg$silentFails === 0) { peg$fail(peg$c18); }
                                            }
                                            if (s21 !== peg$FAILED) {
                                              s22 = peg$parse__();
                                              if (s22 !== peg$FAILED) {
                                                peg$reportedPos = peg$currPos;
                                                s23 = peg$c93();
                                                if (s23) {
                                                  s23 = peg$c30;
                                                } else {
                                                  s23 = peg$c0;
                                                }
                                                if (s23 !== peg$FAILED) {
                                                  s24 = peg$parseconditional();
                                                  if (s24 !== peg$FAILED) {
                                                    peg$reportedPos = peg$currPos;
                                                    s25 = peg$c94(s24);
                                                    if (s25) {
                                                      s25 = peg$c30;
                                                    } else {
                                                      s25 = peg$c0;
                                                    }
                                                    if (s25 !== peg$FAILED) {
                                                      s26 = peg$parse__();
                                                      if (s26 !== peg$FAILED) {
                                                        if (input.charCodeAt(peg$currPos) === 41) {
                                                          s27 = peg$c19;
                                                          peg$currPos++;
                                                        } else {
                                                          s27 = peg$FAILED;
                                                          if (peg$silentFails === 0) { peg$fail(peg$c20); }
                                                        }
                                                        if (s27 !== peg$FAILED) {
                                                          s28 = peg$parseSTOP();
                                                          if (s28 !== peg$FAILED) {
                                                            s29 = peg$parsetemplate();
                                                            if (s29 !== peg$FAILED) {
                                                              peg$reportedPos = s15;
                                                              s16 = peg$c95(s24, s29);
                                                              s15 = s16;
                                                            } else {
                                                              peg$currPos = s15;
                                                              s15 = peg$c0;
                                                            }
                                                          } else {
                                                            peg$currPos = s15;
                                                            s15 = peg$c0;
                                                          }
                                                        } else {
                                                          peg$currPos = s15;
                                                          s15 = peg$c0;
                                                        }
                                                      } else {
                                                        peg$currPos = s15;
                                                        s15 = peg$c0;
                                                      }
                                                    } else {
                                                      peg$currPos = s15;
                                                      s15 = peg$c0;
                                                    }
                                                  } else {
                                                    peg$currPos = s15;
                                                    s15 = peg$c0;
                                                  }
                                                } else {
                                                  peg$currPos = s15;
                                                  s15 = peg$c0;
                                                }
                                              } else {
                                                peg$currPos = s15;
                                                s15 = peg$c0;
                                              }
                                            } else {
                                              peg$currPos = s15;
                                              s15 = peg$c0;
                                            }
                                          } else {
                                            peg$currPos = s15;
                                            s15 = peg$c0;
                                          }
                                        } else {
                                          peg$currPos = s15;
                                          s15 = peg$c0;
                                        }
                                      } else {
                                        peg$currPos = s15;
                                        s15 = peg$c0;
                                      }
                                    } else {
                                      peg$currPos = s15;
                                      s15 = peg$c0;
                                    }
                                  } else {
                                    peg$currPos = s15;
                                    s15 = peg$c0;
                                  }
                                }
                                if (s14 !== peg$FAILED) {
                                  s15 = peg$currPos;
                                  s16 = peg$currPos;
                                  peg$silentFails++;
                                  s17 = peg$currPos;
                                  s18 = peg$parseINDENT();
                                  if (s18 === peg$FAILED) {
                                    s18 = peg$c1;
                                  }
                                  if (s18 !== peg$FAILED) {
                                    s19 = peg$parseSTART_CHAR();
                                    if (s19 !== peg$FAILED) {
                                      if (input.substr(peg$currPos, 5) === peg$c67) {
                                        s20 = peg$c67;
                                        peg$currPos += 5;
                                      } else {
                                        s20 = peg$FAILED;
                                        if (peg$silentFails === 0) { peg$fail(peg$c68); }
                                      }
                                      if (s20 !== peg$FAILED) {
                                        s21 = peg$parseSTOP_CHAR();
                                        if (s21 !== peg$FAILED) {
                                          s18 = [s18, s19, s20, s21];
                                          s17 = s18;
                                        } else {
                                          peg$currPos = s17;
                                          s17 = peg$c0;
                                        }
                                      } else {
                                        peg$currPos = s17;
                                        s17 = peg$c0;
                                      }
                                    } else {
                                      peg$currPos = s17;
                                      s17 = peg$c0;
                                    }
                                  } else {
                                    peg$currPos = s17;
                                    s17 = peg$c0;
                                  }
                                  peg$silentFails--;
                                  if (s17 === peg$FAILED) {
                                    s16 = peg$c30;
                                  } else {
                                    peg$currPos = s16;
                                    s16 = peg$c0;
                                  }
                                  if (s16 !== peg$FAILED) {
                                    s17 = peg$parseINDENT();
                                    if (s17 === peg$FAILED) {
                                      s17 = peg$c1;
                                    }
                                    if (s17 !== peg$FAILED) {
                                      s18 = peg$parseSTART();
                                      if (s18 !== peg$FAILED) {
                                        if (input.substr(peg$currPos, 4) === peg$c65) {
                                          s19 = peg$c65;
                                          peg$currPos += 4;
                                        } else {
                                          s19 = peg$FAILED;
                                          if (peg$silentFails === 0) { peg$fail(peg$c66); }
                                        }
                                        if (s19 !== peg$FAILED) {
                                          s20 = peg$parseSTOP();
                                          if (s20 !== peg$FAILED) {
                                            s21 = peg$parsetemplate();
                                            if (s21 !== peg$FAILED) {
                                              peg$reportedPos = s15;
                                              s16 = peg$c96(s21);
                                              s15 = s16;
                                            } else {
                                              peg$currPos = s15;
                                              s15 = peg$c0;
                                            }
                                          } else {
                                            peg$currPos = s15;
                                            s15 = peg$c0;
                                          }
                                        } else {
                                          peg$currPos = s15;
                                          s15 = peg$c0;
                                        }
                                      } else {
                                        peg$currPos = s15;
                                        s15 = peg$c0;
                                      }
                                    } else {
                                      peg$currPos = s15;
                                      s15 = peg$c0;
                                    }
                                  } else {
                                    peg$currPos = s15;
                                    s15 = peg$c0;
                                  }
                                  if (s15 === peg$FAILED) {
                                    s15 = peg$c1;
                                  }
                                  if (s15 !== peg$FAILED) {
                                    s16 = peg$parseINDENT();
                                    if (s16 === peg$FAILED) {
                                      s16 = peg$c1;
                                    }
                                    if (s16 !== peg$FAILED) {
                                      s17 = peg$parseSTART();
                                      if (s17 !== peg$FAILED) {
                                        if (input.substr(peg$currPos, 5) === peg$c67) {
                                          s18 = peg$c67;
                                          peg$currPos += 5;
                                        } else {
                                          s18 = peg$FAILED;
                                          if (peg$silentFails === 0) { peg$fail(peg$c68); }
                                        }
                                        if (s18 !== peg$FAILED) {
                                          s19 = peg$parseSTOP();
                                          if (s19 !== peg$FAILED) {
                                            peg$reportedPos = s0;
                                            s1 = peg$c97(s1, s8, s13, s14, s15);
                                            s0 = s1;
                                          } else {
                                            peg$currPos = s0;
                                            s0 = peg$c0;
                                          }
                                        } else {
                                          peg$currPos = s0;
                                          s0 = peg$c0;
                                        }
                                      } else {
                                        peg$currPos = s0;
                                        s0 = peg$c0;
                                      }
                                    } else {
                                      peg$currPos = s0;
                                      s0 = peg$c0;
                                    }
                                  } else {
                                    peg$currPos = s0;
                                    s0 = peg$c0;
                                  }
                                } else {
                                  peg$currPos = s0;
                                  s0 = peg$c0;
                                }
                              } else {
                                peg$currPos = s0;
                                s0 = peg$c0;
                              }
                            } else {
                              peg$currPos = s0;
                              s0 = peg$c0;
                            }
                          } else {
                            peg$currPos = s0;
                            s0 = peg$c0;
                          }
                        } else {
                          peg$currPos = s0;
                          s0 = peg$c0;
                        }
                      } else {
                        peg$currPos = s0;
                        s0 = peg$c0;
                      }
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseconditional() {
      var s0, s1, s2, s3, s4, s5;

      s0 = peg$currPos;
      s1 = peg$parseandConditional();
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          if (input.substr(peg$currPos, 2) === peg$c98) {
            s3 = peg$c98;
            peg$currPos += 2;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c99); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              s5 = peg$parseconditional();
              if (s5 !== peg$FAILED) {
                peg$reportedPos = s0;
                s1 = peg$c100(s1, s5);
                s0 = s1;
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$parseandConditional();
      }

      return s0;
    }

    function peg$parseandConditional() {
      var s0, s1, s2, s3, s4, s5;

      s0 = peg$currPos;
      s1 = peg$parsenotConditional();
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          if (input.substr(peg$currPos, 2) === peg$c101) {
            s3 = peg$c101;
            peg$currPos += 2;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c102); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              s5 = peg$parseandConditional();
              if (s5 !== peg$FAILED) {
                peg$reportedPos = s0;
                s1 = peg$c103(s1, s5);
                s0 = s1;
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$parsenotConditional();
      }

      return s0;
    }

    function peg$parsenotConditional() {
      var s0, s1, s2, s3;

      s0 = peg$currPos;
      if (input.charCodeAt(peg$currPos) === 33) {
        s1 = peg$c104;
        peg$currPos++;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c105); }
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          s3 = peg$parsenotConditional();
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c106(s3);
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$parsememberExpr();
      }

      return s0;
    }

    function peg$parseexprOptions() {
      var s0, s1, s2, s3, s4, s5, s6, s7;

      s0 = peg$currPos;
      s1 = peg$parseoption();
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$currPos;
        s4 = peg$parse__();
        if (s4 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 44) {
            s5 = peg$c9;
            peg$currPos++;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c10); }
          }
          if (s5 !== peg$FAILED) {
            s6 = peg$parse__();
            if (s6 !== peg$FAILED) {
              s7 = peg$parseoption();
              if (s7 !== peg$FAILED) {
                peg$reportedPos = s3;
                s4 = peg$c79(s7);
                s3 = s4;
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$currPos;
          s4 = peg$parse__();
          if (s4 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 44) {
              s5 = peg$c9;
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c10); }
            }
            if (s5 !== peg$FAILED) {
              s6 = peg$parse__();
              if (s6 !== peg$FAILED) {
                s7 = peg$parseoption();
                if (s7 !== peg$FAILED) {
                  peg$reportedPos = s3;
                  s4 = peg$c79(s7);
                  s3 = s4;
                } else {
                  peg$currPos = s3;
                  s3 = peg$c0;
                }
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c32(s1, s2);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseoption() {
      var s0, s1, s2, s3, s4, s5, s6;

      s0 = peg$currPos;
      s1 = peg$parseID();
      if (s1 !== peg$FAILED) {
        s2 = peg$currPos;
        s3 = peg$parse__();
        if (s3 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 61) {
            s4 = peg$c34;
            peg$currPos++;
          } else {
            s4 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c35); }
          }
          if (s4 !== peg$FAILED) {
            s5 = peg$parse__();
            if (s5 !== peg$FAILED) {
              s6 = peg$parseexprNoComma();
              if (s6 !== peg$FAILED) {
                peg$reportedPos = s2;
                s3 = peg$c31(s6);
                s2 = s3;
              } else {
                peg$currPos = s2;
                s2 = peg$c0;
              }
            } else {
              peg$currPos = s2;
              s2 = peg$c0;
            }
          } else {
            peg$currPos = s2;
            s2 = peg$c0;
          }
        } else {
          peg$currPos = s2;
          s2 = peg$c0;
        }
        if (s2 === peg$FAILED) {
          s2 = peg$c1;
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c107(s1, s2);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseexprNoComma() {
      var s0, s1, s2, s3, s4;

      s0 = peg$currPos;
      s1 = peg$parsememberExpr();
      if (s1 !== peg$FAILED) {
        s2 = peg$currPos;
        if (input.charCodeAt(peg$currPos) === 58) {
          s3 = peg$c46;
          peg$currPos++;
        } else {
          s3 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c47); }
        }
        if (s3 !== peg$FAILED) {
          s4 = peg$parsemapTemplateRef();
          if (s4 !== peg$FAILED) {
            peg$reportedPos = s2;
            s3 = peg$c108(s4);
            s2 = s3;
          } else {
            peg$currPos = s2;
            s2 = peg$c0;
          }
        } else {
          peg$currPos = s2;
          s2 = peg$c0;
        }
        if (s2 === peg$FAILED) {
          s2 = peg$c1;
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c109(s1, s2);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseexpr() {
      var s0, s1;

      peg$silentFails++;
      s0 = peg$parsemapExpr();
      peg$silentFails--;
      if (s0 === peg$FAILED) {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c110); }
      }

      return s0;
    }

    function peg$parsemapExpr() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14;

      s0 = peg$currPos;
      s1 = peg$parsememberExpr();
      if (s1 !== peg$FAILED) {
        s2 = peg$currPos;
        s3 = [];
        s4 = peg$currPos;
        s5 = peg$parse__();
        if (s5 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 44) {
            s6 = peg$c9;
            peg$currPos++;
          } else {
            s6 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c10); }
          }
          if (s6 !== peg$FAILED) {
            s7 = peg$parse__();
            if (s7 !== peg$FAILED) {
              s8 = peg$parsememberExpr();
              if (s8 !== peg$FAILED) {
                peg$reportedPos = s4;
                s5 = peg$c111(s8);
                s4 = s5;
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
        } else {
          peg$currPos = s4;
          s4 = peg$c0;
        }
        if (s4 !== peg$FAILED) {
          while (s4 !== peg$FAILED) {
            s3.push(s4);
            s4 = peg$currPos;
            s5 = peg$parse__();
            if (s5 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 44) {
                s6 = peg$c9;
                peg$currPos++;
              } else {
                s6 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c10); }
              }
              if (s6 !== peg$FAILED) {
                s7 = peg$parse__();
                if (s7 !== peg$FAILED) {
                  s8 = peg$parsememberExpr();
                  if (s8 !== peg$FAILED) {
                    peg$reportedPos = s4;
                    s5 = peg$c111(s8);
                    s4 = s5;
                  } else {
                    peg$currPos = s4;
                    s4 = peg$c0;
                  }
                } else {
                  peg$currPos = s4;
                  s4 = peg$c0;
                }
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          }
        } else {
          s3 = peg$c0;
        }
        if (s3 !== peg$FAILED) {
          s4 = peg$parse__();
          if (s4 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 58) {
              s5 = peg$c46;
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c47); }
            }
            if (s5 !== peg$FAILED) {
              s6 = peg$parse__();
              if (s6 !== peg$FAILED) {
                s7 = peg$parsemapTemplateRef();
                if (s7 !== peg$FAILED) {
                  peg$reportedPos = s2;
                  s3 = peg$c112(s3, s7);
                  s2 = s3;
                } else {
                  peg$currPos = s2;
                  s2 = peg$c0;
                }
              } else {
                peg$currPos = s2;
                s2 = peg$c0;
              }
            } else {
              peg$currPos = s2;
              s2 = peg$c0;
            }
          } else {
            peg$currPos = s2;
            s2 = peg$c0;
          }
        } else {
          peg$currPos = s2;
          s2 = peg$c0;
        }
        if (s2 === peg$FAILED) {
          s2 = peg$c1;
        }
        if (s2 !== peg$FAILED) {
          s3 = [];
          s4 = peg$currPos;
          s5 = peg$parse__();
          if (s5 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 58) {
              s6 = peg$c46;
              peg$currPos++;
            } else {
              s6 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c47); }
            }
            if (s6 !== peg$FAILED) {
              s7 = peg$parse__();
              if (s7 !== peg$FAILED) {
                s8 = peg$parsemapTemplateRef();
                if (s8 !== peg$FAILED) {
                  s9 = [];
                  s10 = peg$currPos;
                  s11 = peg$parse__();
                  if (s11 !== peg$FAILED) {
                    if (input.charCodeAt(peg$currPos) === 44) {
                      s12 = peg$c9;
                      peg$currPos++;
                    } else {
                      s12 = peg$FAILED;
                      if (peg$silentFails === 0) { peg$fail(peg$c10); }
                    }
                    if (s12 !== peg$FAILED) {
                      s13 = peg$parse__();
                      if (s13 !== peg$FAILED) {
                        s14 = peg$parsemapTemplateRef();
                        if (s14 !== peg$FAILED) {
                          peg$reportedPos = s10;
                          s11 = peg$c113(s14);
                          s10 = s11;
                        } else {
                          peg$currPos = s10;
                          s10 = peg$c0;
                        }
                      } else {
                        peg$currPos = s10;
                        s10 = peg$c0;
                      }
                    } else {
                      peg$currPos = s10;
                      s10 = peg$c0;
                    }
                  } else {
                    peg$currPos = s10;
                    s10 = peg$c0;
                  }
                  while (s10 !== peg$FAILED) {
                    s9.push(s10);
                    s10 = peg$currPos;
                    s11 = peg$parse__();
                    if (s11 !== peg$FAILED) {
                      if (input.charCodeAt(peg$currPos) === 44) {
                        s12 = peg$c9;
                        peg$currPos++;
                      } else {
                        s12 = peg$FAILED;
                        if (peg$silentFails === 0) { peg$fail(peg$c10); }
                      }
                      if (s12 !== peg$FAILED) {
                        s13 = peg$parse__();
                        if (s13 !== peg$FAILED) {
                          s14 = peg$parsemapTemplateRef();
                          if (s14 !== peg$FAILED) {
                            peg$reportedPos = s10;
                            s11 = peg$c113(s14);
                            s10 = s11;
                          } else {
                            peg$currPos = s10;
                            s10 = peg$c0;
                          }
                        } else {
                          peg$currPos = s10;
                          s10 = peg$c0;
                        }
                      } else {
                        peg$currPos = s10;
                        s10 = peg$c0;
                      }
                    } else {
                      peg$currPos = s10;
                      s10 = peg$c0;
                    }
                  }
                  if (s9 !== peg$FAILED) {
                    peg$reportedPos = s4;
                    s5 = peg$c114(s8, s9);
                    s4 = s5;
                  } else {
                    peg$currPos = s4;
                    s4 = peg$c0;
                  }
                } else {
                  peg$currPos = s4;
                  s4 = peg$c0;
                }
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
          while (s4 !== peg$FAILED) {
            s3.push(s4);
            s4 = peg$currPos;
            s5 = peg$parse__();
            if (s5 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 58) {
                s6 = peg$c46;
                peg$currPos++;
              } else {
                s6 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c47); }
              }
              if (s6 !== peg$FAILED) {
                s7 = peg$parse__();
                if (s7 !== peg$FAILED) {
                  s8 = peg$parsemapTemplateRef();
                  if (s8 !== peg$FAILED) {
                    s9 = [];
                    s10 = peg$currPos;
                    s11 = peg$parse__();
                    if (s11 !== peg$FAILED) {
                      if (input.charCodeAt(peg$currPos) === 44) {
                        s12 = peg$c9;
                        peg$currPos++;
                      } else {
                        s12 = peg$FAILED;
                        if (peg$silentFails === 0) { peg$fail(peg$c10); }
                      }
                      if (s12 !== peg$FAILED) {
                        s13 = peg$parse__();
                        if (s13 !== peg$FAILED) {
                          s14 = peg$parsemapTemplateRef();
                          if (s14 !== peg$FAILED) {
                            peg$reportedPos = s10;
                            s11 = peg$c113(s14);
                            s10 = s11;
                          } else {
                            peg$currPos = s10;
                            s10 = peg$c0;
                          }
                        } else {
                          peg$currPos = s10;
                          s10 = peg$c0;
                        }
                      } else {
                        peg$currPos = s10;
                        s10 = peg$c0;
                      }
                    } else {
                      peg$currPos = s10;
                      s10 = peg$c0;
                    }
                    while (s10 !== peg$FAILED) {
                      s9.push(s10);
                      s10 = peg$currPos;
                      s11 = peg$parse__();
                      if (s11 !== peg$FAILED) {
                        if (input.charCodeAt(peg$currPos) === 44) {
                          s12 = peg$c9;
                          peg$currPos++;
                        } else {
                          s12 = peg$FAILED;
                          if (peg$silentFails === 0) { peg$fail(peg$c10); }
                        }
                        if (s12 !== peg$FAILED) {
                          s13 = peg$parse__();
                          if (s13 !== peg$FAILED) {
                            s14 = peg$parsemapTemplateRef();
                            if (s14 !== peg$FAILED) {
                              peg$reportedPos = s10;
                              s11 = peg$c113(s14);
                              s10 = s11;
                            } else {
                              peg$currPos = s10;
                              s10 = peg$c0;
                            }
                          } else {
                            peg$currPos = s10;
                            s10 = peg$c0;
                          }
                        } else {
                          peg$currPos = s10;
                          s10 = peg$c0;
                        }
                      } else {
                        peg$currPos = s10;
                        s10 = peg$c0;
                      }
                    }
                    if (s9 !== peg$FAILED) {
                      peg$reportedPos = s4;
                      s5 = peg$c114(s8, s9);
                      s4 = s5;
                    } else {
                      peg$currPos = s4;
                      s4 = peg$c0;
                    }
                  } else {
                    peg$currPos = s4;
                    s4 = peg$c0;
                  }
                } else {
                  peg$currPos = s4;
                  s4 = peg$c0;
                }
              } else {
                peg$currPos = s4;
                s4 = peg$c0;
              }
            } else {
              peg$currPos = s4;
              s4 = peg$c0;
            }
          }
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c115(s1, s2, s3);
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parsemapTemplateRef() {
      var s0, s1, s2, s3, s4, s5, s6;

      s0 = peg$currPos;
      s1 = peg$parseID();
      if (s1 !== peg$FAILED) {
        if (input.charCodeAt(peg$currPos) === 40) {
          s2 = peg$c17;
          peg$currPos++;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c18); }
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$parseargs();
          if (s3 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 41) {
              s4 = peg$c19;
              peg$currPos++;
            } else {
              s4 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c20); }
            }
            if (s4 !== peg$FAILED) {
              peg$reportedPos = s0;
              s1 = peg$c116(s1, s3);
              s0 = s1;
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$parsesubtemplate();
        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          if (input.charCodeAt(peg$currPos) === 40) {
            s1 = peg$c17;
            peg$currPos++;
          } else {
            s1 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c18); }
          }
          if (s1 !== peg$FAILED) {
            s2 = peg$parsemapExpr();
            if (s2 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 41) {
                s3 = peg$c19;
                peg$currPos++;
              } else {
                s3 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c20); }
              }
              if (s3 !== peg$FAILED) {
                if (input.charCodeAt(peg$currPos) === 40) {
                  s4 = peg$c17;
                  peg$currPos++;
                } else {
                  s4 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c18); }
                }
                if (s4 !== peg$FAILED) {
                  s5 = peg$parseargExprList();
                  if (s5 === peg$FAILED) {
                    s5 = peg$c1;
                  }
                  if (s5 !== peg$FAILED) {
                    if (input.charCodeAt(peg$currPos) === 41) {
                      s6 = peg$c19;
                      peg$currPos++;
                    } else {
                      s6 = peg$FAILED;
                      if (peg$silentFails === 0) { peg$fail(peg$c20); }
                    }
                    if (s6 !== peg$FAILED) {
                      s1 = [s1, s2, s3, s4, s5, s6];
                      s0 = s1;
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        }
      }

      return s0;
    }

    function peg$parsememberExpr() {
      var s0, s1, s2, s3, s4, s5, s6, s7;

      s0 = peg$currPos;
      s1 = peg$parseincludeExpr();
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$currPos;
        if (input.charCodeAt(peg$currPos) === 46) {
          s4 = peg$c15;
          peg$currPos++;
        } else {
          s4 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c16); }
        }
        if (s4 !== peg$FAILED) {
          s5 = peg$parseID();
          if (s5 !== peg$FAILED) {
            peg$reportedPos = s3;
            s4 = peg$c117(s5);
            s3 = s4;
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        if (s3 === peg$FAILED) {
          s3 = peg$currPos;
          if (input.charCodeAt(peg$currPos) === 46) {
            s4 = peg$c15;
            peg$currPos++;
          } else {
            s4 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c16); }
          }
          if (s4 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 40) {
              s5 = peg$c17;
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c18); }
            }
            if (s5 !== peg$FAILED) {
              s6 = peg$parsemapExpr();
              if (s6 !== peg$FAILED) {
                if (input.charCodeAt(peg$currPos) === 41) {
                  s7 = peg$c19;
                  peg$currPos++;
                } else {
                  s7 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c20); }
                }
                if (s7 !== peg$FAILED) {
                  peg$reportedPos = s3;
                  s4 = peg$c118(s6);
                  s3 = s4;
                } else {
                  peg$currPos = s3;
                  s3 = peg$c0;
                }
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        }
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$currPos;
          if (input.charCodeAt(peg$currPos) === 46) {
            s4 = peg$c15;
            peg$currPos++;
          } else {
            s4 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c16); }
          }
          if (s4 !== peg$FAILED) {
            s5 = peg$parseID();
            if (s5 !== peg$FAILED) {
              peg$reportedPos = s3;
              s4 = peg$c117(s5);
              s3 = s4;
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
          if (s3 === peg$FAILED) {
            s3 = peg$currPos;
            if (input.charCodeAt(peg$currPos) === 46) {
              s4 = peg$c15;
              peg$currPos++;
            } else {
              s4 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c16); }
            }
            if (s4 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 40) {
                s5 = peg$c17;
                peg$currPos++;
              } else {
                s5 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c18); }
              }
              if (s5 !== peg$FAILED) {
                s6 = peg$parsemapExpr();
                if (s6 !== peg$FAILED) {
                  if (input.charCodeAt(peg$currPos) === 41) {
                    s7 = peg$c19;
                    peg$currPos++;
                  } else {
                    s7 = peg$FAILED;
                    if (peg$silentFails === 0) { peg$fail(peg$c20); }
                  }
                  if (s7 !== peg$FAILED) {
                    peg$reportedPos = s3;
                    s4 = peg$c118(s6);
                    s3 = s4;
                  } else {
                    peg$currPos = s3;
                    s3 = peg$c0;
                  }
                } else {
                  peg$currPos = s3;
                  s3 = peg$c0;
                }
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          }
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c119(s1, s2);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseincludeExpr() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8;

      s0 = peg$currPos;
      s1 = peg$parseID();
      if (s1 !== peg$FAILED) {
        peg$reportedPos = peg$currPos;
        s2 = peg$c120(s1);
        if (s2) {
          s2 = peg$c30;
        } else {
          s2 = peg$c0;
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$parse__();
          if (s3 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 40) {
              s4 = peg$c17;
              peg$currPos++;
            } else {
              s4 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c18); }
            }
            if (s4 !== peg$FAILED) {
              s5 = peg$parse__();
              if (s5 !== peg$FAILED) {
                s6 = peg$parseexpr();
                if (s6 === peg$FAILED) {
                  s6 = peg$c1;
                }
                if (s6 !== peg$FAILED) {
                  s7 = peg$parse__();
                  if (s7 !== peg$FAILED) {
                    if (input.charCodeAt(peg$currPos) === 41) {
                      s8 = peg$c19;
                      peg$currPos++;
                    } else {
                      s8 = peg$FAILED;
                      if (peg$silentFails === 0) { peg$fail(peg$c20); }
                    }
                    if (s8 !== peg$FAILED) {
                      peg$reportedPos = s0;
                      s1 = peg$c121(s1, s6);
                      s0 = s1;
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        if (input.substr(peg$currPos, 6) === peg$c122) {
          s1 = peg$c122;
          peg$currPos += 6;
        } else {
          s1 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c123); }
        }
        if (s1 !== peg$FAILED) {
          s2 = peg$parseID();
          if (s2 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 40) {
              s3 = peg$c17;
              peg$currPos++;
            } else {
              s3 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c18); }
            }
            if (s3 !== peg$FAILED) {
              s4 = peg$parseargs();
              if (s4 !== peg$FAILED) {
                if (input.charCodeAt(peg$currPos) === 41) {
                  s5 = peg$c19;
                  peg$currPos++;
                } else {
                  s5 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c20); }
                }
                if (s5 !== peg$FAILED) {
                  peg$reportedPos = s0;
                  s1 = peg$c124(s2, s4);
                  s0 = s1;
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          s1 = peg$parseID();
          if (s1 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 40) {
              s2 = peg$c17;
              peg$currPos++;
            } else {
              s2 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c18); }
            }
            if (s2 !== peg$FAILED) {
              s3 = peg$parseargs();
              if (s3 !== peg$FAILED) {
                if (input.charCodeAt(peg$currPos) === 41) {
                  s4 = peg$c19;
                  peg$currPos++;
                } else {
                  s4 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c20); }
                }
                if (s4 !== peg$FAILED) {
                  peg$reportedPos = s0;
                  s1 = peg$c125(s1, s3);
                  s0 = s1;
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
          if (s0 === peg$FAILED) {
            s0 = peg$parseprimary();
          }
        }
      }

      return s0;
    }

    function peg$parseprimary() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8;

      s0 = peg$parseTRUE();
      if (s0 === peg$FAILED) {
        s0 = peg$parseFALSE();
        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          s1 = peg$parseID();
          if (s1 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c126(s1);
          }
          s0 = s1;
          if (s0 === peg$FAILED) {
            s0 = peg$currPos;
            s1 = peg$parseSTRING();
            if (s1 !== peg$FAILED) {
              peg$reportedPos = s0;
              s1 = peg$c127(s1);
            }
            s0 = s1;
            if (s0 === peg$FAILED) {
              s0 = peg$parsesubtemplate();
              if (s0 === peg$FAILED) {
                s0 = peg$parselist();
                if (s0 === peg$FAILED) {
                  s0 = peg$currPos;
                  peg$reportedPos = peg$currPos;
                  s1 = peg$c128();
                  if (s1) {
                    s1 = peg$c30;
                  } else {
                    s1 = peg$c0;
                  }
                  if (s1 !== peg$FAILED) {
                    if (input.charCodeAt(peg$currPos) === 40) {
                      s2 = peg$c17;
                      peg$currPos++;
                    } else {
                      s2 = peg$FAILED;
                      if (peg$silentFails === 0) { peg$fail(peg$c18); }
                    }
                    if (s2 !== peg$FAILED) {
                      s3 = peg$parseconditional();
                      if (s3 !== peg$FAILED) {
                        if (input.charCodeAt(peg$currPos) === 41) {
                          s4 = peg$c19;
                          peg$currPos++;
                        } else {
                          s4 = peg$FAILED;
                          if (peg$silentFails === 0) { peg$fail(peg$c20); }
                        }
                        if (s4 !== peg$FAILED) {
                          peg$reportedPos = s0;
                          s1 = peg$c129(s3);
                          s0 = s1;
                        } else {
                          peg$currPos = s0;
                          s0 = peg$c0;
                        }
                      } else {
                        peg$currPos = s0;
                        s0 = peg$c0;
                      }
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                  if (s0 === peg$FAILED) {
                    s0 = peg$currPos;
                    peg$reportedPos = peg$currPos;
                    s1 = peg$c130();
                    if (s1) {
                      s1 = peg$c30;
                    } else {
                      s1 = peg$c0;
                    }
                    if (s1 !== peg$FAILED) {
                      if (input.charCodeAt(peg$currPos) === 40) {
                        s2 = peg$c17;
                        peg$currPos++;
                      } else {
                        s2 = peg$FAILED;
                        if (peg$silentFails === 0) { peg$fail(peg$c18); }
                      }
                      if (s2 !== peg$FAILED) {
                        s3 = peg$parseexpr();
                        if (s3 !== peg$FAILED) {
                          if (input.charCodeAt(peg$currPos) === 41) {
                            s4 = peg$c19;
                            peg$currPos++;
                          } else {
                            s4 = peg$FAILED;
                            if (peg$silentFails === 0) { peg$fail(peg$c20); }
                          }
                          if (s4 !== peg$FAILED) {
                            s5 = peg$currPos;
                            if (input.charCodeAt(peg$currPos) === 40) {
                              s6 = peg$c17;
                              peg$currPos++;
                            } else {
                              s6 = peg$FAILED;
                              if (peg$silentFails === 0) { peg$fail(peg$c18); }
                            }
                            if (s6 !== peg$FAILED) {
                              s7 = peg$parseargExprList();
                              if (s7 === peg$FAILED) {
                                s7 = peg$c1;
                              }
                              if (s7 !== peg$FAILED) {
                                if (input.charCodeAt(peg$currPos) === 41) {
                                  s8 = peg$c19;
                                  peg$currPos++;
                                } else {
                                  s8 = peg$FAILED;
                                  if (peg$silentFails === 0) { peg$fail(peg$c20); }
                                }
                                if (s8 !== peg$FAILED) {
                                  peg$reportedPos = s5;
                                  s6 = peg$c131(s7);
                                  s5 = s6;
                                } else {
                                  peg$currPos = s5;
                                  s5 = peg$c0;
                                }
                              } else {
                                peg$currPos = s5;
                                s5 = peg$c0;
                              }
                            } else {
                              peg$currPos = s5;
                              s5 = peg$c0;
                            }
                            if (s5 === peg$FAILED) {
                              s5 = peg$c1;
                            }
                            if (s5 !== peg$FAILED) {
                              peg$reportedPos = s0;
                              s1 = peg$c132(s3, s5);
                              s0 = s1;
                            } else {
                              peg$currPos = s0;
                              s0 = peg$c0;
                            }
                          } else {
                            peg$currPos = s0;
                            s0 = peg$c0;
                          }
                        } else {
                          peg$currPos = s0;
                          s0 = peg$c0;
                        }
                      } else {
                        peg$currPos = s0;
                        s0 = peg$c0;
                      }
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  }
                }
              }
            }
          }
        }
      }

      return s0;
    }

    function peg$parseargs() {
      var s0, s1, s2, s3, s4, s5, s6, s7;

      s0 = peg$currPos;
      s1 = peg$parsenamedArg();
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$currPos;
        s4 = peg$parse__();
        if (s4 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 44) {
            s5 = peg$c9;
            peg$currPos++;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c10); }
          }
          if (s5 !== peg$FAILED) {
            s6 = peg$parse__();
            if (s6 !== peg$FAILED) {
              s7 = peg$parsenamedArg();
              if (s7 !== peg$FAILED) {
                peg$reportedPos = s3;
                s4 = peg$c131(s7);
                s3 = s4;
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$currPos;
          s4 = peg$parse__();
          if (s4 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 44) {
              s5 = peg$c9;
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c10); }
            }
            if (s5 !== peg$FAILED) {
              s6 = peg$parse__();
              if (s6 !== peg$FAILED) {
                s7 = peg$parsenamedArg();
                if (s7 !== peg$FAILED) {
                  peg$reportedPos = s3;
                  s4 = peg$c131(s7);
                  s3 = s4;
                } else {
                  peg$currPos = s3;
                  s3 = peg$c0;
                }
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$currPos;
          s4 = peg$parse__();
          if (s4 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 44) {
              s5 = peg$c9;
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c10); }
            }
            if (s5 !== peg$FAILED) {
              s6 = peg$parse__();
              if (s6 !== peg$FAILED) {
                if (input.substr(peg$currPos, 3) === peg$c133) {
                  s7 = peg$c133;
                  peg$currPos += 3;
                } else {
                  s7 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c134); }
                }
                if (s7 !== peg$FAILED) {
                  peg$reportedPos = s3;
                  s4 = peg$c135(s7);
                  s3 = s4;
                } else {
                  peg$currPos = s3;
                  s3 = peg$c0;
                }
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
          if (s3 === peg$FAILED) {
            s3 = peg$c1;
          }
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c136(s1, s2, s3);
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        if (input.substr(peg$currPos, 3) === peg$c133) {
          s1 = peg$c133;
          peg$currPos += 3;
        } else {
          s1 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c134); }
        }
        if (s1 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c137();
        }
        s0 = s1;
        if (s0 === peg$FAILED) {
          s0 = peg$parseargExprList();
        }
      }

      return s0;
    }

    function peg$parseargExprList() {
      var s0, s1, s2, s3, s4, s5, s6, s7;

      s0 = peg$currPos;
      s1 = peg$parseexprNoComma();
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$currPos;
        s4 = peg$parse__();
        if (s4 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 44) {
            s5 = peg$c9;
            peg$currPos++;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c10); }
          }
          if (s5 !== peg$FAILED) {
            s6 = peg$parse__();
            if (s6 !== peg$FAILED) {
              s7 = peg$parseexprNoComma();
              if (s7 !== peg$FAILED) {
                peg$reportedPos = s3;
                s4 = peg$c131(s7);
                s3 = s4;
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$currPos;
          s4 = peg$parse__();
          if (s4 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 44) {
              s5 = peg$c9;
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c10); }
            }
            if (s5 !== peg$FAILED) {
              s6 = peg$parse__();
              if (s6 !== peg$FAILED) {
                s7 = peg$parseexprNoComma();
                if (s7 !== peg$FAILED) {
                  peg$reportedPos = s3;
                  s4 = peg$c131(s7);
                  s3 = s4;
                } else {
                  peg$currPos = s3;
                  s3 = peg$c0;
                }
              } else {
                peg$currPos = s3;
                s3 = peg$c0;
              }
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c138(s1, s2);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        s1 = [];
        if (s1 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c139();
        }
        s0 = s1;
      }

      return s0;
    }

    function peg$parsenamedArg() {
      var s0, s1, s2, s3, s4, s5;

      s0 = peg$currPos;
      s1 = peg$parseID();
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 61) {
            s3 = peg$c34;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c35); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parse__();
            if (s4 !== peg$FAILED) {
              s5 = peg$parseexprNoComma();
              if (s5 !== peg$FAILED) {
                peg$reportedPos = s0;
                s1 = peg$c140(s1, s5);
                s0 = s1;
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parselist() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;

      s0 = peg$currPos;
      if (input.charCodeAt(peg$currPos) === 91) {
        s1 = peg$c40;
        peg$currPos++;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c41); }
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          s3 = peg$parselistElement();
          if (s3 === peg$FAILED) {
            s3 = peg$c1;
          }
          if (s3 !== peg$FAILED) {
            s4 = [];
            s5 = peg$currPos;
            s6 = peg$parse__();
            if (s6 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 44) {
                s7 = peg$c9;
                peg$currPos++;
              } else {
                s7 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c10); }
              }
              if (s7 !== peg$FAILED) {
                s8 = peg$parse__();
                if (s8 !== peg$FAILED) {
                  s9 = peg$parselistElement();
                  if (s9 !== peg$FAILED) {
                    peg$reportedPos = s5;
                    s6 = peg$c69(s9);
                    s5 = s6;
                  } else {
                    peg$currPos = s5;
                    s5 = peg$c0;
                  }
                } else {
                  peg$currPos = s5;
                  s5 = peg$c0;
                }
              } else {
                peg$currPos = s5;
                s5 = peg$c0;
              }
            } else {
              peg$currPos = s5;
              s5 = peg$c0;
            }
            while (s5 !== peg$FAILED) {
              s4.push(s5);
              s5 = peg$currPos;
              s6 = peg$parse__();
              if (s6 !== peg$FAILED) {
                if (input.charCodeAt(peg$currPos) === 44) {
                  s7 = peg$c9;
                  peg$currPos++;
                } else {
                  s7 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c10); }
                }
                if (s7 !== peg$FAILED) {
                  s8 = peg$parse__();
                  if (s8 !== peg$FAILED) {
                    s9 = peg$parselistElement();
                    if (s9 !== peg$FAILED) {
                      peg$reportedPos = s5;
                      s6 = peg$c69(s9);
                      s5 = s6;
                    } else {
                      peg$currPos = s5;
                      s5 = peg$c0;
                    }
                  } else {
                    peg$currPos = s5;
                    s5 = peg$c0;
                  }
                } else {
                  peg$currPos = s5;
                  s5 = peg$c0;
                }
              } else {
                peg$currPos = s5;
                s5 = peg$c0;
              }
            }
            if (s4 !== peg$FAILED) {
              s5 = peg$parse__();
              if (s5 !== peg$FAILED) {
                if (input.charCodeAt(peg$currPos) === 93) {
                  s6 = peg$c42;
                  peg$currPos++;
                } else {
                  s6 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c43); }
                }
                if (s6 !== peg$FAILED) {
                  peg$reportedPos = s0;
                  s1 = peg$c141(s3, s4);
                  s0 = s1;
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parselistElement() {
      var s0, s1;

      s0 = peg$parseexprNoComma();
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        s1 = [];
        if (s1 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c12();
        }
        s0 = s1;
      }

      return s0;
    }

    function peg$parseWS_CHAR() {
      var s0;

      if (input.charCodeAt(peg$currPos) === 32) {
        s0 = peg$c142;
        peg$currPos++;
      } else {
        s0 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c143); }
      }
      if (s0 === peg$FAILED) {
        if (input.charCodeAt(peg$currPos) === 9) {
          s0 = peg$c144;
          peg$currPos++;
        } else {
          s0 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c145); }
        }
      }

      return s0;
    }

    function peg$parseEOL() {
      var s0, s1;

      peg$silentFails++;
      if (input.charCodeAt(peg$currPos) === 10) {
        s0 = peg$c147;
        peg$currPos++;
      } else {
        s0 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c148); }
      }
      if (s0 === peg$FAILED) {
        if (input.substr(peg$currPos, 2) === peg$c149) {
          s0 = peg$c149;
          peg$currPos += 2;
        } else {
          s0 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c150); }
        }
        if (s0 === peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 13) {
            s0 = peg$c151;
            peg$currPos++;
          } else {
            s0 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c152); }
          }
        }
      }
      peg$silentFails--;
      if (s0 === peg$FAILED) {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c146); }
      }

      return s0;
    }

    function peg$parseCOMMENT() {
      var s0, s1, s2, s3, s4, s5;

      s0 = peg$currPos;
      if (input.substr(peg$currPos, 2) === peg$c153) {
        s1 = peg$c153;
        peg$currPos += 2;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c154); }
      }
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$currPos;
        s4 = peg$currPos;
        peg$silentFails++;
        if (input.substr(peg$currPos, 2) === peg$c155) {
          s5 = peg$c155;
          peg$currPos += 2;
        } else {
          s5 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c156); }
        }
        peg$silentFails--;
        if (s5 === peg$FAILED) {
          s4 = peg$c30;
        } else {
          peg$currPos = s4;
          s4 = peg$c0;
        }
        if (s4 !== peg$FAILED) {
          if (input.length > peg$currPos) {
            s5 = input.charAt(peg$currPos);
            peg$currPos++;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c157); }
          }
          if (s5 !== peg$FAILED) {
            s4 = [s4, s5];
            s3 = s4;
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$currPos;
          s4 = peg$currPos;
          peg$silentFails++;
          if (input.substr(peg$currPos, 2) === peg$c155) {
            s5 = peg$c155;
            peg$currPos += 2;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c156); }
          }
          peg$silentFails--;
          if (s5 === peg$FAILED) {
            s4 = peg$c30;
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
          if (s4 !== peg$FAILED) {
            if (input.length > peg$currPos) {
              s5 = input.charAt(peg$currPos);
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c157); }
            }
            if (s5 !== peg$FAILED) {
              s4 = [s4, s5];
              s3 = s4;
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        }
        if (s2 !== peg$FAILED) {
          if (input.substr(peg$currPos, 2) === peg$c155) {
            s3 = peg$c155;
            peg$currPos += 2;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c156); }
          }
          if (s3 !== peg$FAILED) {
            s1 = [s1, s2, s3];
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseLINE_COMMENT() {
      var s0, s1, s2, s3, s4, s5;

      s0 = peg$currPos;
      if (input.substr(peg$currPos, 2) === peg$c158) {
        s1 = peg$c158;
        peg$currPos += 2;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c159); }
      }
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$currPos;
        s4 = peg$currPos;
        peg$silentFails++;
        s5 = peg$parseEOL();
        peg$silentFails--;
        if (s5 === peg$FAILED) {
          s4 = peg$c30;
        } else {
          peg$currPos = s4;
          s4 = peg$c0;
        }
        if (s4 !== peg$FAILED) {
          if (input.length > peg$currPos) {
            s5 = input.charAt(peg$currPos);
            peg$currPos++;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c157); }
          }
          if (s5 !== peg$FAILED) {
            s4 = [s4, s5];
            s3 = s4;
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$currPos;
          s4 = peg$currPos;
          peg$silentFails++;
          s5 = peg$parseEOL();
          peg$silentFails--;
          if (s5 === peg$FAILED) {
            s4 = peg$c30;
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
          if (s4 !== peg$FAILED) {
            if (input.length > peg$currPos) {
              s5 = input.charAt(peg$currPos);
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c157); }
            }
            if (s5 !== peg$FAILED) {
              s4 = [s4, s5];
              s3 = s4;
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        }
        if (s2 !== peg$FAILED) {
          s1 = [s1, s2];
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parse__() {
      var s0, s1;

      peg$silentFails++;
      s0 = [];
      s1 = peg$parseWS_CHAR();
      if (s1 === peg$FAILED) {
        s1 = peg$parseEOL();
        if (s1 === peg$FAILED) {
          s1 = peg$parseCOMMENT();
          if (s1 === peg$FAILED) {
            s1 = peg$parseLINE_COMMENT();
          }
        }
      }
      while (s1 !== peg$FAILED) {
        s0.push(s1);
        s1 = peg$parseWS_CHAR();
        if (s1 === peg$FAILED) {
          s1 = peg$parseEOL();
          if (s1 === peg$FAILED) {
            s1 = peg$parseCOMMENT();
            if (s1 === peg$FAILED) {
              s1 = peg$parseLINE_COMMENT();
            }
          }
        }
      }
      peg$silentFails--;
      if (s0 === peg$FAILED) {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c160); }
      }

      return s0;
    }

    function peg$parseID() {
      var s0, s1, s2, s3, s4;

      peg$silentFails++;
      s0 = peg$currPos;
      s1 = peg$currPos;
      peg$silentFails++;
      s2 = peg$parseRESERVED();
      peg$silentFails--;
      if (s2 === peg$FAILED) {
        s1 = peg$c30;
      } else {
        peg$currPos = s1;
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        if (peg$c162.test(input.charAt(peg$currPos))) {
          s2 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c163); }
        }
        if (s2 !== peg$FAILED) {
          s3 = [];
          if (peg$c164.test(input.charAt(peg$currPos))) {
            s4 = input.charAt(peg$currPos);
            peg$currPos++;
          } else {
            s4 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c165); }
          }
          while (s4 !== peg$FAILED) {
            s3.push(s4);
            if (peg$c164.test(input.charAt(peg$currPos))) {
              s4 = input.charAt(peg$currPos);
              peg$currPos++;
            } else {
              s4 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c165); }
            }
          }
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c166();
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      peg$silentFails--;
      if (s0 === peg$FAILED) {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c161); }
      }

      return s0;
    }

    function peg$parseRESERVED() {
      var s0;

      if (input.substr(peg$currPos, 4) === peg$c167) {
        s0 = peg$c167;
        peg$currPos += 4;
      } else {
        s0 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c168); }
      }
      if (s0 === peg$FAILED) {
        if (input.substr(peg$currPos, 5) === peg$c169) {
          s0 = peg$c169;
          peg$currPos += 5;
        } else {
          s0 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c170); }
        }
        if (s0 === peg$FAILED) {
          if (input.substr(peg$currPos, 2) === peg$c89) {
            s0 = peg$c89;
            peg$currPos += 2;
          } else {
            s0 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c90); }
          }
          if (s0 === peg$FAILED) {
            if (input.substr(peg$currPos, 5) === peg$c171) {
              s0 = peg$c171;
              peg$currPos += 5;
            } else {
              s0 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c172); }
            }
            if (s0 === peg$FAILED) {
              if (input.substr(peg$currPos, 7) === peg$c173) {
                s0 = peg$c173;
                peg$currPos += 7;
              } else {
                s0 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c174); }
              }
              if (s0 === peg$FAILED) {
                if (input.substr(peg$currPos, 6) === peg$c175) {
                  s0 = peg$c175;
                  peg$currPos += 6;
                } else {
                  s0 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c176); }
                }
                if (s0 === peg$FAILED) {
                  if (input.substr(peg$currPos, 5) === peg$c177) {
                    s0 = peg$c177;
                    peg$currPos += 5;
                  } else {
                    s0 = peg$FAILED;
                    if (peg$silentFails === 0) { peg$fail(peg$c178); }
                  }
                  if (s0 === peg$FAILED) {
                    if (input.substr(peg$currPos, 5) === peg$c179) {
                      s0 = peg$c179;
                      peg$currPos += 5;
                    } else {
                      s0 = peg$FAILED;
                      if (peg$silentFails === 0) { peg$fail(peg$c180); }
                    }
                    if (s0 === peg$FAILED) {
                      if (input.substr(peg$currPos, 10) === peg$c7) {
                        s0 = peg$c7;
                        peg$currPos += 10;
                      } else {
                        s0 = peg$FAILED;
                        if (peg$silentFails === 0) { peg$fail(peg$c8); }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }

      return s0;
    }

    function peg$parseTRUE() {
      var s0, s1;

      s0 = peg$currPos;
      if (input.substr(peg$currPos, 4) === peg$c167) {
        s1 = peg$c167;
        peg$currPos += 4;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c168); }
      }
      if (s1 !== peg$FAILED) {
        peg$reportedPos = s0;
        s1 = peg$c181();
      }
      s0 = s1;

      return s0;
    }

    function peg$parseFALSE() {
      var s0, s1;

      s0 = peg$currPos;
      if (input.substr(peg$currPos, 5) === peg$c169) {
        s1 = peg$c169;
        peg$currPos += 5;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c170); }
      }
      if (s1 !== peg$FAILED) {
        peg$reportedPos = s0;
        s1 = peg$c182();
      }
      s0 = s1;

      return s0;
    }

    function peg$parseEMPTY_LIST() {
      var s0, s1, s2, s3;

      s0 = peg$currPos;
      if (input.charCodeAt(peg$currPos) === 91) {
        s1 = peg$c40;
        peg$currPos++;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c41); }
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parse__();
        if (s2 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 93) {
            s3 = peg$c42;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c43); }
          }
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c183();
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseSTRING() {
      var s0, s1, s2, s3;

      peg$silentFails++;
      s0 = peg$currPos;
      if (input.charCodeAt(peg$currPos) === 34) {
        s1 = peg$c185;
        peg$currPos++;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c186); }
      }
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$parseSTRING_CHAR();
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$parseSTRING_CHAR();
        }
        if (s2 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 34) {
            s3 = peg$c185;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c186); }
          }
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c187(s2);
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      peg$silentFails--;
      if (s0 === peg$FAILED) {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c184); }
      }

      return s0;
    }

    function peg$parseSTRING_CHAR() {
      var s0, s1, s2;

      s0 = peg$currPos;
      s1 = peg$currPos;
      peg$silentFails++;
      if (input.charCodeAt(peg$currPos) === 34) {
        s2 = peg$c185;
        peg$currPos++;
      } else {
        s2 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c186); }
      }
      if (s2 === peg$FAILED) {
        if (input.charCodeAt(peg$currPos) === 92) {
          s2 = peg$c188;
          peg$currPos++;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c189); }
        }
        if (s2 === peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 13) {
            s2 = peg$c151;
            peg$currPos++;
          } else {
            s2 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c152); }
          }
          if (s2 === peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 10) {
              s2 = peg$c147;
              peg$currPos++;
            } else {
              s2 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c148); }
            }
          }
        }
      }
      peg$silentFails--;
      if (s2 === peg$FAILED) {
        s1 = peg$c30;
      } else {
        peg$currPos = s1;
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        if (input.length > peg$currPos) {
          s2 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c157); }
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c190();
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        if (input.charCodeAt(peg$currPos) === 92) {
          s1 = peg$c188;
          peg$currPos++;
        } else {
          s1 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c189); }
        }
        if (s1 !== peg$FAILED) {
          s2 = peg$parseESCAPE_CHAR();
          if (s2 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c191(s2);
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          s1 = peg$parseEOL();
          if (s1 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c192();
          }
          s0 = s1;
        }
      }

      return s0;
    }

    function peg$parseESCAPE_CHAR() {
      var s0, s1;

      s0 = peg$currPos;
      if (input.charCodeAt(peg$currPos) === 110) {
        s1 = peg$c193;
        peg$currPos++;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c194); }
      }
      if (s1 !== peg$FAILED) {
        peg$reportedPos = s0;
        s1 = peg$c195();
      }
      s0 = s1;
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        if (input.charCodeAt(peg$currPos) === 114) {
          s1 = peg$c196;
          peg$currPos++;
        } else {
          s1 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c197); }
        }
        if (s1 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c198();
        }
        s0 = s1;
        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          if (input.charCodeAt(peg$currPos) === 116) {
            s1 = peg$c199;
            peg$currPos++;
          } else {
            s1 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c200); }
          }
          if (s1 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c201();
          }
          s0 = s1;
          if (s0 === peg$FAILED) {
            s0 = peg$currPos;
            if (input.length > peg$currPos) {
              s1 = input.charAt(peg$currPos);
              peg$currPos++;
            } else {
              s1 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c157); }
            }
            if (s1 !== peg$FAILED) {
              peg$reportedPos = s0;
              s1 = peg$c190();
            }
            s0 = s1;
          }
        }
      }

      return s0;
    }

    function peg$parseBIGSTRING() {
      var s0, s1, s2, s3;

      peg$silentFails++;
      s0 = peg$currPos;
      if (input.substr(peg$currPos, 2) === peg$c203) {
        s1 = peg$c203;
        peg$currPos += 2;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c204); }
      }
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$parseBIGSTRING_CHAR();
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$parseBIGSTRING_CHAR();
        }
        if (s2 !== peg$FAILED) {
          if (input.substr(peg$currPos, 2) === peg$c205) {
            s3 = peg$c205;
            peg$currPos += 2;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c206); }
          }
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c207(s2);
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      peg$silentFails--;
      if (s0 === peg$FAILED) {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c202); }
      }

      return s0;
    }

    function peg$parseBIGSTRING_CHAR() {
      var s0, s1, s2;

      s0 = peg$currPos;
      s1 = peg$currPos;
      peg$silentFails++;
      if (input.substr(peg$currPos, 2) === peg$c205) {
        s2 = peg$c205;
        peg$currPos += 2;
      } else {
        s2 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c206); }
      }
      if (s2 === peg$FAILED) {
        if (input.substr(peg$currPos, 3) === peg$c208) {
          s2 = peg$c208;
          peg$currPos += 3;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c209); }
        }
        if (s2 === peg$FAILED) {
          if (input.substr(peg$currPos, 3) === peg$c210) {
            s2 = peg$c210;
            peg$currPos += 3;
          } else {
            s2 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c211); }
          }
        }
      }
      peg$silentFails--;
      if (s2 === peg$FAILED) {
        s1 = peg$c30;
      } else {
        peg$currPos = s1;
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        if (input.length > peg$currPos) {
          s2 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c157); }
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c190();
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        if (input.substr(peg$currPos, 3) === peg$c208) {
          s1 = peg$c208;
          peg$currPos += 3;
        } else {
          s1 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c209); }
        }
        if (s1 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c212();
        }
        s0 = s1;
        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          if (input.substr(peg$currPos, 3) === peg$c210) {
            s1 = peg$c210;
            peg$currPos += 3;
          } else {
            s1 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c211); }
          }
          if (s1 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c212();
          }
          s0 = s1;
          if (s0 === peg$FAILED) {
            s0 = peg$currPos;
            s1 = peg$parseEOF();
            if (s1 !== peg$FAILED) {
              peg$reportedPos = s0;
              s1 = peg$c213();
            }
            s0 = s1;
          }
        }
      }

      return s0;
    }

    function peg$parseBIGSTRING_NO_NL() {
      var s0, s1, s2, s3, s4, s5;

      peg$silentFails++;
      s0 = peg$currPos;
      if (input.substr(peg$currPos, 2) === peg$c214) {
        s1 = peg$c214;
        peg$currPos += 2;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c215); }
      }
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$currPos;
        s4 = peg$currPos;
        peg$silentFails++;
        if (input.substr(peg$currPos, 2) === peg$c216) {
          s5 = peg$c216;
          peg$currPos += 2;
        } else {
          s5 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c217); }
        }
        peg$silentFails--;
        if (s5 === peg$FAILED) {
          s4 = peg$c30;
        } else {
          peg$currPos = s4;
          s4 = peg$c0;
        }
        if (s4 !== peg$FAILED) {
          if (input.length > peg$currPos) {
            s5 = input.charAt(peg$currPos);
            peg$currPos++;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c157); }
          }
          if (s5 !== peg$FAILED) {
            s4 = [s4, s5];
            s3 = s4;
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        while (s3 !== peg$FAILED) {
          s2.push(s3);
          s3 = peg$currPos;
          s4 = peg$currPos;
          peg$silentFails++;
          if (input.substr(peg$currPos, 2) === peg$c216) {
            s5 = peg$c216;
            peg$currPos += 2;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c217); }
          }
          peg$silentFails--;
          if (s5 === peg$FAILED) {
            s4 = peg$c30;
          } else {
            peg$currPos = s4;
            s4 = peg$c0;
          }
          if (s4 !== peg$FAILED) {
            if (input.length > peg$currPos) {
              s5 = input.charAt(peg$currPos);
              peg$currPos++;
            } else {
              s5 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c157); }
            }
            if (s5 !== peg$FAILED) {
              s4 = [s4, s5];
              s3 = s4;
            } else {
              peg$currPos = s3;
              s3 = peg$c0;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        }
        if (s2 !== peg$FAILED) {
          if (input.substr(peg$currPos, 2) === peg$c216) {
            s3 = peg$c216;
            peg$currPos += 2;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c217); }
          }
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c218();
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      peg$silentFails--;
      if (s0 === peg$FAILED) {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c202); }
      }

      return s0;
    }

    function peg$parseEOF() {
      var s0, s1;

      peg$silentFails++;
      s0 = peg$currPos;
      peg$silentFails++;
      if (input.length > peg$currPos) {
        s1 = input.charAt(peg$currPos);
        peg$currPos++;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c157); }
      }
      peg$silentFails--;
      if (s1 === peg$FAILED) {
        s0 = peg$c30;
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      peg$silentFails--;
      if (s0 === peg$FAILED) {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c219); }
      }

      return s0;
    }

    function peg$parseINDENT() {
      var s0, s1, s2, s3;

      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c220();
      if (s1) {
        s1 = peg$c30;
      } else {
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$parseWS_CHAR();
        if (s3 !== peg$FAILED) {
          while (s3 !== peg$FAILED) {
            s2.push(s3);
            s3 = peg$parseWS_CHAR();
          }
        } else {
          s2 = peg$c0;
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c221();
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseSTART() {
      var s0, s1, s2, s3, s4, s5;

      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c222();
      if (s1) {
        s1 = peg$c30;
      } else {
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$currPos;
        peg$silentFails++;
        s3 = peg$currPos;
        s4 = peg$parseSTART_CHAR();
        if (s4 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 33) {
            s5 = peg$c104;
            peg$currPos++;
          } else {
            s5 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c105); }
          }
          if (s5 !== peg$FAILED) {
            s4 = [s4, s5];
            s3 = s4;
          } else {
            peg$currPos = s3;
            s3 = peg$c0;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$c0;
        }
        peg$silentFails--;
        if (s3 === peg$FAILED) {
          s2 = peg$c30;
        } else {
          peg$currPos = s2;
          s2 = peg$c0;
        }
        if (s2 !== peg$FAILED) {
          s3 = peg$parseSTART_CHAR();
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c223();
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseSTART_CHAR() {
      var s0, s1, s2;

      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c224();
      if (s1) {
        s1 = peg$c30;
      } else {
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        if (input.length > peg$currPos) {
          s2 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c157); }
        }
        if (s2 !== peg$FAILED) {
          s1 = [s1, s2];
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseST_COMMENT() {
      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;

      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c222();
      if (s1) {
        s1 = peg$c30;
      } else {
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parseSTART_CHAR();
        if (s2 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 33) {
            s3 = peg$c104;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c105); }
          }
          if (s3 !== peg$FAILED) {
            s4 = [];
            s5 = peg$currPos;
            s6 = peg$currPos;
            peg$silentFails++;
            s7 = peg$currPos;
            if (input.charCodeAt(peg$currPos) === 33) {
              s8 = peg$c104;
              peg$currPos++;
            } else {
              s8 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c105); }
            }
            if (s8 !== peg$FAILED) {
              s9 = peg$parseSTOP_CHAR();
              if (s9 !== peg$FAILED) {
                s8 = [s8, s9];
                s7 = s8;
              } else {
                peg$currPos = s7;
                s7 = peg$c0;
              }
            } else {
              peg$currPos = s7;
              s7 = peg$c0;
            }
            peg$silentFails--;
            if (s7 === peg$FAILED) {
              s6 = peg$c30;
            } else {
              peg$currPos = s6;
              s6 = peg$c0;
            }
            if (s6 !== peg$FAILED) {
              if (input.length > peg$currPos) {
                s7 = input.charAt(peg$currPos);
                peg$currPos++;
              } else {
                s7 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c157); }
              }
              if (s7 !== peg$FAILED) {
                s6 = [s6, s7];
                s5 = s6;
              } else {
                peg$currPos = s5;
                s5 = peg$c0;
              }
            } else {
              peg$currPos = s5;
              s5 = peg$c0;
            }
            while (s5 !== peg$FAILED) {
              s4.push(s5);
              s5 = peg$currPos;
              s6 = peg$currPos;
              peg$silentFails++;
              s7 = peg$currPos;
              if (input.charCodeAt(peg$currPos) === 33) {
                s8 = peg$c104;
                peg$currPos++;
              } else {
                s8 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c105); }
              }
              if (s8 !== peg$FAILED) {
                s9 = peg$parseSTOP_CHAR();
                if (s9 !== peg$FAILED) {
                  s8 = [s8, s9];
                  s7 = s8;
                } else {
                  peg$currPos = s7;
                  s7 = peg$c0;
                }
              } else {
                peg$currPos = s7;
                s7 = peg$c0;
              }
              peg$silentFails--;
              if (s7 === peg$FAILED) {
                s6 = peg$c30;
              } else {
                peg$currPos = s6;
                s6 = peg$c0;
              }
              if (s6 !== peg$FAILED) {
                if (input.length > peg$currPos) {
                  s7 = input.charAt(peg$currPos);
                  peg$currPos++;
                } else {
                  s7 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c157); }
                }
                if (s7 !== peg$FAILED) {
                  s6 = [s6, s7];
                  s5 = s6;
                } else {
                  peg$currPos = s5;
                  s5 = peg$c0;
                }
              } else {
                peg$currPos = s5;
                s5 = peg$c0;
              }
            }
            if (s4 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 33) {
                s5 = peg$c104;
                peg$currPos++;
              } else {
                s5 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c105); }
              }
              if (s5 !== peg$FAILED) {
                s6 = peg$parseSTOP_CHAR();
                if (s6 !== peg$FAILED) {
                  peg$reportedPos = s0;
                  s1 = peg$c225();
                  s0 = s1;
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$c0;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$c0;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseTEXT() {
      var s0, s1, s2, s3;

      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c222();
      if (s1) {
        s1 = peg$c30;
      } else {
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        s2 = [];
        s3 = peg$parseTEXT_CHAR();
        if (s3 !== peg$FAILED) {
          while (s3 !== peg$FAILED) {
            s2.push(s3);
            s3 = peg$parseTEXT_CHAR();
          }
        } else {
          s2 = peg$c0;
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c226(s2);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseTEXT_CHAR() {
      var s0, s1, s2, s3, s4, s5;

      s0 = peg$currPos;
      s1 = peg$currPos;
      peg$silentFails++;
      s2 = peg$parseEOL();
      if (s2 === peg$FAILED) {
        s2 = peg$parseSTART_CHAR();
        if (s2 === peg$FAILED) {
          s2 = peg$currPos;
          if (input.charCodeAt(peg$currPos) === 92) {
            s3 = peg$c188;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c189); }
          }
          if (s3 !== peg$FAILED) {
            s4 = peg$parseSTART_CHAR();
            if (s4 !== peg$FAILED) {
              s3 = [s3, s4];
              s2 = s3;
            } else {
              peg$currPos = s2;
              s2 = peg$c0;
            }
          } else {
            peg$currPos = s2;
            s2 = peg$c0;
          }
          if (s2 === peg$FAILED) {
            if (input.substr(peg$currPos, 2) === peg$c227) {
              s2 = peg$c227;
              peg$currPos += 2;
            } else {
              s2 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c228); }
            }
            if (s2 === peg$FAILED) {
              if (input.substr(peg$currPos, 2) === peg$c229) {
                s2 = peg$c229;
                peg$currPos += 2;
              } else {
                s2 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c230); }
              }
              if (s2 === peg$FAILED) {
                s2 = peg$currPos;
                peg$reportedPos = peg$currPos;
                s3 = peg$c231();
                if (s3) {
                  s3 = peg$c30;
                } else {
                  s3 = peg$c0;
                }
                if (s3 !== peg$FAILED) {
                  if (input.charCodeAt(peg$currPos) === 125) {
                    s4 = peg$c57;
                    peg$currPos++;
                  } else {
                    s4 = peg$FAILED;
                    if (peg$silentFails === 0) { peg$fail(peg$c58); }
                  }
                  if (s4 !== peg$FAILED) {
                    s3 = [s3, s4];
                    s2 = s3;
                  } else {
                    peg$currPos = s2;
                    s2 = peg$c0;
                  }
                } else {
                  peg$currPos = s2;
                  s2 = peg$c0;
                }
              }
            }
          }
        }
      }
      peg$silentFails--;
      if (s2 === peg$FAILED) {
        s1 = peg$c30;
      } else {
        peg$currPos = s1;
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        if (input.length > peg$currPos) {
          s2 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c157); }
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c232();
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      if (s0 === peg$FAILED) {
        s0 = peg$currPos;
        if (input.charCodeAt(peg$currPos) === 92) {
          s1 = peg$c188;
          peg$currPos++;
        } else {
          s1 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c189); }
        }
        if (s1 !== peg$FAILED) {
          s2 = peg$parseSTART_CHAR();
          if (s2 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c233();
            s0 = s1;
          } else {
            peg$currPos = s0;
            s0 = peg$c0;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          if (input.substr(peg$currPos, 2) === peg$c227) {
            s1 = peg$c227;
            peg$currPos += 2;
          } else {
            s1 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c228); }
          }
          if (s1 !== peg$FAILED) {
            peg$reportedPos = s0;
            s1 = peg$c234();
          }
          s0 = s1;
          if (s0 === peg$FAILED) {
            s0 = peg$currPos;
            if (input.substr(peg$currPos, 2) === peg$c229) {
              s1 = peg$c229;
              peg$currPos += 2;
            } else {
              s1 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c230); }
            }
            if (s1 !== peg$FAILED) {
              peg$reportedPos = s0;
              s1 = peg$c235();
            }
            s0 = s1;
            if (s0 === peg$FAILED) {
              s0 = peg$currPos;
              if (input.charCodeAt(peg$currPos) === 92) {
                s1 = peg$c188;
                peg$currPos++;
              } else {
                s1 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c189); }
              }
              if (s1 !== peg$FAILED) {
                peg$reportedPos = s0;
                s1 = peg$c234();
              }
              s0 = s1;
              if (s0 === peg$FAILED) {
                s0 = peg$currPos;
                s1 = peg$parseSTART_CHAR();
                if (s1 !== peg$FAILED) {
                  s2 = peg$currPos;
                  peg$silentFails++;
                  if (input.substr(peg$currPos, 2) === peg$c227) {
                    s3 = peg$c227;
                    peg$currPos += 2;
                  } else {
                    s3 = peg$FAILED;
                    if (peg$silentFails === 0) { peg$fail(peg$c228); }
                  }
                  peg$silentFails--;
                  if (s3 === peg$FAILED) {
                    s2 = peg$c30;
                  } else {
                    peg$currPos = s2;
                    s2 = peg$c0;
                  }
                  if (s2 !== peg$FAILED) {
                    s3 = peg$parseESCAPE();
                    if (s3 !== peg$FAILED) {
                      s4 = peg$parseSTOP_CHAR();
                      if (s4 !== peg$FAILED) {
                        peg$reportedPos = s0;
                        s1 = peg$c31(s3);
                        s0 = s1;
                      } else {
                        peg$currPos = s0;
                        s0 = peg$c0;
                      }
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$c0;
                }
                if (s0 === peg$FAILED) {
                  s0 = peg$currPos;
                  s1 = peg$parseSTART_CHAR();
                  if (s1 !== peg$FAILED) {
                    if (input.substr(peg$currPos, 2) === peg$c227) {
                      s2 = peg$c227;
                      peg$currPos += 2;
                    } else {
                      s2 = peg$FAILED;
                      if (peg$silentFails === 0) { peg$fail(peg$c228); }
                    }
                    if (s2 !== peg$FAILED) {
                      s3 = peg$parseSTOP_CHAR();
                      if (s3 !== peg$FAILED) {
                        s4 = [];
                        s5 = peg$parseWS_CHAR();
                        while (s5 !== peg$FAILED) {
                          s4.push(s5);
                          s5 = peg$parseWS_CHAR();
                        }
                        if (s4 !== peg$FAILED) {
                          s5 = peg$parseEOL();
                          if (s5 !== peg$FAILED) {
                            peg$reportedPos = s0;
                            s1 = peg$c236();
                            s0 = s1;
                          } else {
                            peg$currPos = s0;
                            s0 = peg$c0;
                          }
                        } else {
                          peg$currPos = s0;
                          s0 = peg$c0;
                        }
                      } else {
                        peg$currPos = s0;
                        s0 = peg$c0;
                      }
                    } else {
                      peg$currPos = s0;
                      s0 = peg$c0;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$c0;
                  }
                }
              }
            }
          }
        }
      }

      return s0;
    }

    function peg$parseESCAPE() {
      var s0, s1, s2, s3, s4, s5, s6, s7;

      s0 = peg$currPos;
      if (input.charCodeAt(peg$currPos) === 92) {
        s1 = peg$c188;
        peg$currPos++;
      } else {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c189); }
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$currPos;
        if (input.charCodeAt(peg$currPos) === 117) {
          s3 = peg$c237;
          peg$currPos++;
        } else {
          s3 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c238); }
        }
        if (s3 !== peg$FAILED) {
          s4 = peg$parseHEX_DIGIT();
          if (s4 !== peg$FAILED) {
            s5 = peg$parseHEX_DIGIT();
            if (s5 !== peg$FAILED) {
              s6 = peg$parseHEX_DIGIT();
              if (s6 !== peg$FAILED) {
                s7 = peg$parseHEX_DIGIT();
                if (s7 !== peg$FAILED) {
                  peg$reportedPos = s2;
                  s3 = peg$c239();
                  s2 = s3;
                } else {
                  peg$currPos = s2;
                  s2 = peg$c0;
                }
              } else {
                peg$currPos = s2;
                s2 = peg$c0;
              }
            } else {
              peg$currPos = s2;
              s2 = peg$c0;
            }
          } else {
            peg$currPos = s2;
            s2 = peg$c0;
          }
        } else {
          peg$currPos = s2;
          s2 = peg$c0;
        }
        if (s2 === peg$FAILED) {
          s2 = peg$currPos;
          if (input.charCodeAt(peg$currPos) === 110) {
            s3 = peg$c193;
            peg$currPos++;
          } else {
            s3 = peg$FAILED;
            if (peg$silentFails === 0) { peg$fail(peg$c194); }
          }
          if (s3 !== peg$FAILED) {
            peg$reportedPos = s2;
            s3 = peg$c195();
          }
          s2 = s3;
          if (s2 === peg$FAILED) {
            s2 = peg$currPos;
            if (input.charCodeAt(peg$currPos) === 116) {
              s3 = peg$c199;
              peg$currPos++;
            } else {
              s3 = peg$FAILED;
              if (peg$silentFails === 0) { peg$fail(peg$c200); }
            }
            if (s3 !== peg$FAILED) {
              peg$reportedPos = s2;
              s3 = peg$c201();
            }
            s2 = s3;
            if (s2 === peg$FAILED) {
              s2 = peg$currPos;
              if (input.charCodeAt(peg$currPos) === 32) {
                s3 = peg$c142;
                peg$currPos++;
              } else {
                s3 = peg$FAILED;
                if (peg$silentFails === 0) { peg$fail(peg$c143); }
              }
              if (s3 !== peg$FAILED) {
                peg$reportedPos = s2;
                s3 = peg$c240();
              }
              s2 = s3;
              if (s2 === peg$FAILED) {
                s2 = peg$currPos;
                if (input.length > peg$currPos) {
                  s3 = input.charAt(peg$currPos);
                  peg$currPos++;
                } else {
                  s3 = peg$FAILED;
                  if (peg$silentFails === 0) { peg$fail(peg$c157); }
                }
                if (s3 !== peg$FAILED) {
                  peg$reportedPos = s2;
                  s3 = peg$c241();
                }
                s2 = s3;
              }
            }
          }
        }
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c242(s2);
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseHEX_DIGIT() {
      var s0;

      if (peg$c243.test(input.charAt(peg$currPos))) {
        s0 = input.charAt(peg$currPos);
        peg$currPos++;
      } else {
        s0 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c244); }
      }

      return s0;
    }

    function peg$parseNEWLINE() {
      var s0, s1, s2;

      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c222();
      if (s1) {
        s1 = peg$c30;
      } else {
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parseEOL();
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c245();
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }

    function peg$parseSTOP() {
      var s0, s1, s2;

      peg$silentFails++;
      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c222();
      if (s1) {
        s1 = peg$c0;
      } else {
        s1 = peg$c30;
      }
      if (s1 !== peg$FAILED) {
        s2 = peg$parseSTOP_CHAR();
        if (s2 !== peg$FAILED) {
          peg$reportedPos = s0;
          s1 = peg$c247();
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }
      peg$silentFails--;
      if (s0 === peg$FAILED) {
        s1 = peg$FAILED;
        if (peg$silentFails === 0) { peg$fail(peg$c246); }
      }

      return s0;
    }

    function peg$parseSTOP_CHAR() {
      var s0, s1, s2;

      s0 = peg$currPos;
      peg$reportedPos = peg$currPos;
      s1 = peg$c248();
      if (s1) {
        s1 = peg$c30;
      } else {
        s1 = peg$c0;
      }
      if (s1 !== peg$FAILED) {
        if (input.length > peg$currPos) {
          s2 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s2 = peg$FAILED;
          if (peg$silentFails === 0) { peg$fail(peg$c157); }
        }
        if (s2 !== peg$FAILED) {
          s1 = [s1, s2];
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$c0;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$c0;
      }

      return s0;
    }


        var VALID_DELIMITERS =  "#$%^&*<>";

        var delimiterStartChar = "<",
            delimiterStopChar = ">",
            curGroup = options.group,
            curDict = null,
            outside = true, // tell if we are inside or outside a template: outside<inside>outside
            subtemplateDepth = 0, // handle nesting of subtemplates: { ... {...} ...}
            inConditional = false,
            verbose = false,
            ignoreNewLines = options.ignoreNewLines || false,
            formalArgsHasOptional = false,
            lineOffset = options.lineOffset || 0;

        var logger = function(message) {
            console.log(message);
        };

        function verboseLog(message) {
            if (verbose) {
                logger(message);
            }
        }

        function getLocation() {
            return {
                line: line() + lineOffset,
                column: column()
            };
        }

        function makeList(first, rest) {
            var list;
            if (first && rest) {
                list = [first].concat(rest);
            } else if (first) {
                list = [first];
            } else if (rest) {
                list = rest;
            } else {
                list = [];
            }
            return list;
        }

        function parseTemplate(template) {
            var ignoreNewLines,
                lineOffset = line() - 1;

            ignoreNewLines = false;
            if (template.ignoreNewLines) {
                ignoreNewLines = true;
                template = template.string;
            }
            if (template.charAt(0) === "\n" || (template.charAt(0) === "\r" && template.charAt(1) === "\n")) {
                lineOffset += 1;
            }
            template = template.replace(/^\r?\n/, "") // remove a single leading new line if any
            template = template.replace(/\r?\n$/, "") // remove a single trailing new line if any

            outside = true; // just in case, make sure always start parsing a template on the outside
            try {
                return parse(template, {
                    startRule: "templateAndEOF",
                    group: curGroup,
                    nested: true,
                    verbose: verbose,
                    lineOffset: lineOffset,
                    ignoreNewLines: ignoreNewLines,
                    delimiterStartChar: delimiterStartChar,
                    delimiterStopChar: delimiterStopChar
                });
            } catch(ex) {
                if (ex instanceof SyntaxError) {
                    ex.line += lineOffset;
                }
                throw ex;
            }
        }

        delimiterStartChar = options.delimiterStartChar || "<";
        delimiterStopChar = options.delimiterStopChar || ">";
        verbose = options.verbose || false;
        if (options.logger) {
            logger = options.logger;
        }

        if (!options.nested) {
            verboseLog("Default delimiters: " + delimiterStartChar + ", " + delimiterStopChar);
        }



    peg$result = peg$startRuleFunction();

    if (peg$result !== peg$FAILED && peg$currPos === input.length) {
      return peg$result;
    } else {
      if (peg$result !== peg$FAILED && peg$currPos < input.length) {
        peg$fail({ type: "end", description: "end of input" });
      }

      throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
    }
  }

  return {
    SyntaxError: SyntaxError,
    parse:       parse
  };
})();